Skip to content

Commit

Permalink
WIP: credentials validation
Browse files Browse the repository at this point in the history
do a pre-flight check of permissions using cloud-credentials-operator validation to do a check on the creds being used for installation

the initial list of permissions that gathers the AWS actions needed to perform an installation are taken verbatim from the IAM group permissions the hive team has been using to perform installation/uninstallation with (there absolutely could be some excess actions that used to be needed, but may no longer be needed)

note that the permissions checks are done with the assumption of IAM policies consisting of 'Resource: "*"'. so a list of ["ec2:CreateRoute", "ec2:CreateSubnet"] is evaluated as whether we can peform

```
{
    "Statement": [
        {
            "Action": [
                "ec2:CreateRoute",
                "ec2:CreateSubnet"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
```
  • Loading branch information
Joel Diaz committed Jan 31, 2019
1 parent 749d9e5 commit 85eb699
Show file tree
Hide file tree
Showing 27 changed files with 4,451 additions and 7 deletions.
34 changes: 28 additions & 6 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

229 changes: 228 additions & 1 deletion pkg/asset/installconfig/platformcredscheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,188 @@ package installconfig
import (
"fmt"

"github.com/sirupsen/logrus"

"github.com/gophercloud/utils/openstack/clientconfig"
"github.com/openshift/installer/pkg/asset"
awsconfig "github.com/openshift/installer/pkg/asset/installconfig/aws"
"github.com/openshift/installer/pkg/types/aws"
"github.com/openshift/installer/pkg/types/libvirt"
"github.com/openshift/installer/pkg/types/none"
"github.com/openshift/installer/pkg/types/openstack"

ccaws "github.com/openshift/cloud-credential-operator/pkg/aws"
credvalidator "github.com/openshift/cloud-credential-operator/pkg/controller/utils"
)

var installPermissionsAWS = []string{
// EC2 related perms
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AssociateDhcpOptions",
"ec2:AssociateRouteTable",
"ec2:AttachInternetGateway",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateDhcpOptions",
"ec2:CreateInternetGateway",
"ec2:CreateNatGateway",
"ec2:CreateRoute",
"ec2:CreateRouteTable",
"ec2:CreateSecurityGroup",
"ec2:CreateSubnet",
"ec2:CreateTags",
"ec2:CreateVpc",
"ec2:CreateVpcEndpoint",
"ec2:CreateVolume",
"ec2:DescribeAccountAttributes",
"ec2:DescribeAddresses",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeDhcpOptions",
"ec2:DescribeImages",
"ec2:DescribeInstanceAttribute",
"ec2:DescribeInstanceCreditSpecifications",
"ec2:DescribeInstances",
"ec2:DescribeInternetGateways",
"ec2:DescribeKeyPairs",
"ec2:DescribeNatGateways",
"ec2:DescribeNetworkAcls",
"ec2:DescribePrefixLists",
"ec2:DescribeRegions",
"ec2:DescribeRouteTables",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeTags",
"ec2:DescribeVpcEndpoints",
"ec2:DescribeVpcs",
"ec2:DescribeVpcAttribute",
"ec2:DescribeVolumes",
"ec2:DescribeVpcClassicLink",
"ec2:DescribeVpcClassicLinkDnsSupport",
"ec2:ModifyInstanceAttribute",
"ec2:ModifySubnetAttribute",
"ec2:ModifyVpcAttribute",
"ec2:RevokeSecurityGroupEgress",
"ec2:RunInstances",
"ec2:TerminateInstances",
"ec2:DeleteDhcpOptions",
"ec2:DeleteRoute",
"ec2:RevokeSecurityGroupIngress",
"ec2:DisassociateRouteTable",
"ec2:ReplaceRouteTableAssociation",
"ec2:DeleteRouteTable",
"ec2:DeleteSubnet",
"ec2:DescribeNetworkInterfaces",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:DeleteNatGateway",
"ec2:DeleteSecurityGroup",
"ec2:DetachInternetGateway",
"ec2:DeleteInternetGateway",
"ec2:ReleaseAddress",
"ec2:DeleteVpc",

// ELB related perms
"elasticloadbalancing:AddTags",
"elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
"elasticloadbalancing:AttachLoadBalancerToSubnets",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateLoadBalancerListeners",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:ConfigureHealthCheck",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:DescribeInstanceHealth",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"elasticloadbalancing:DescribeTags",
"elasticloadbalancing:DescribeTargetGroupAttributes",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:ModifyTargetGroupAttributes",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:SetLoadBalancerPoliciesOfListener",

// IAM related perms
"iam:AddRoleToInstanceProfile",
"iam:CreateInstanceProfile",
"iam:CreateRole",
"iam:GetInstanceProfile",
"iam:GetUser",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:PassRole",
"iam:PutRolePolicy",
"iam:DeleteRolePolicy",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:ListInstanceProfilesForRole",
"iam:ListRoles",
"iam:DeleteRole",

// Route53 related perms
"route53:ChangeResourceRecordSets",
"route53:ChangeTagsForResource",
"route53:GetChange",
"route53:GetHostedZone",
"route53:CreateHostedZone",
"route53:DeleteHostedZone",
"route53:ListHostedZones",
"route53:ListHostedZonesByName",
"route53:ListResourceRecordSets",
"route53:ListTagsForResource",
"route53:UpdateHostedZoneComment",

// S3 related perms
"s3:CreateBucket",
"s3:ListBucket",
"s3:GetBucketCors",
"s3:GetBucketWebsite",
"s3:GetBucketVersioning",
"s3:GetAccelerateConfiguration",
"s3:GetEncryptionConfiguration",
"s3:GetBucketRequestPayment",
"s3:GetBucketLogging",
"s3:GetLifecycleConfiguration",
"s3:GetBucketReplication",
"s3:GetReplicationConfiguration",
"s3:GetBucketLocation",
"s3:GetBucketTagging",
"s3:DeleteBucket",
"s3:PutBucketAcl",
"s3:PutBucketTagging",
"s3:PutEncryptionConfiguration",

// More S3 (would be nice to )
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectTagging",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectTagging",
"s3:GetObjectVersion",
"s3:DeleteObject",

// ???
"sts:GetCallerIdentity",

// Uninstall-specific perms
"autoscaling:DescribeAutoScalingGroups",
"ec2:DeleteNetworkInterface",
"ec2:DeleteVolume",
"ec2:DeleteVpcEndpoints",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DeleteTargetGroup",
"iam:ListInstanceProfiles",
"iam:ListRolePolicies",
"s3:ListAllMyBuckets",
"tag:GetResources",
}

// PlatformCredsCheck is an asset that checks the platform credentials, asks for them or errors out if invalid
// the cluster.
type PlatformCredsCheck struct {
Expand All @@ -35,7 +208,7 @@ func (a *PlatformCredsCheck) Generate(dependencies asset.Parents) error {
platform := ic.Config.Platform.Name()
switch platform {
case aws.Name:
_, err = awsconfig.GetSession()
err = validateAWSCreds()
case libvirt.Name:
case none.Name:
case openstack.Name:
Expand All @@ -46,10 +219,64 @@ func (a *PlatformCredsCheck) Generate(dependencies asset.Parents) error {
err = fmt.Errorf("unknown platform type %q", platform)
}

if err != nil {
return err
}

if ic != nil {
panic(fmt.Sprintf("XXX DONT PROVISION"))
}

return err
}

// Name returns the human-friendly name of the asset.
func (a *PlatformCredsCheck) Name() string {
return "Platform Credentials Check"
}

func validateAWSCreds() error {
ssn, err := awsconfig.GetSession()
if err != nil {
return err
}

creds, err := ssn.Config.Credentials.Get()
if err != nil {
return err
}

logger := logrus.New()
awsClient, err := ccaws.NewClient([]byte(creds.AccessKeyID), []byte(creds.SecretAccessKey))
if err != nil {
return fmt.Errorf("error building aws client to check credentials against: %v", err)
}

// Check whether we can do an installation
canInstall, err := credvalidator.CheckPermissionsAgainstActions(awsClient, installPermissionsAWS, logger)
if err != nil {
return fmt.Errorf("error checking whether we have enough permissions to install: %v", err)
}
if !canInstall {
return fmt.Errorf("current credentials insufficient for performing cluster installation")
}

// Check whether we can mint new creds for cluster services interacting with the cloud
canMint, err := credvalidator.CheckCloudCredCreation(awsClient, logger)
if err != nil {
return fmt.Errorf("error checking whether we can mint new creds with current credentials: %v", err)
}

// Check whether we can use the current credentials in passthrough mode to satisfy
// cluster services interacting with the cloud
canPassthrough, err := credvalidator.CheckCloudCredPassthrough(awsClient, logger)
if err != nil {
return fmt.Errorf("error checking whether we can use current creds in passthrough mode: %v", err)
}

if !canMint && !canPassthrough {
return fmt.Errorf("AWS credentials cannot be used to either create new creds or use as-is")
}

return nil
}
Loading

0 comments on commit 85eb699

Please sign in to comment.