Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1868350: Backport new feature to bypass problems with AWS Accounts using SCP #4046

Merged
merged 2 commits into from Aug 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions data/data/install.openshift.io_installconfigs.yaml
Expand Up @@ -609,6 +609,28 @@ spec:
- name
- platform
type: object
credentialsMode:
description: "CredentialsMode is used to explicitly set the mode with
which CredentialRequests are satisfied. \n If this field is set, then
the installer will not attempt to query the cloud permissions before
attempting installation. If the field is not set or empty, then the
installer will perform its normal verification that the credentials
provided are sufficient to perform an installation. \n There are three
possible values for this field, but the valid values are dependent upon
the platform being used. \"Mint\": create new credentials with a subset
of the overall permissions for each CredentialsRequest \"Passthrough\":
copy the credentials with all of the overall permissions for each CredentialsRequest
\"Manual\": CredentialsRequests must be handled manually by the user
\n For each of the following platforms, the field can set to the specified
values. For all other platforms, the field must not be set. AWS: \"Mint\",
\"Passthrough\", \"Manual\" Azure: \"Mint\", \"Passthrough\" GCP: \"Mint\",
\"Passthrough\""
enum:
- ""
- Mint
- Passthrough
- Manual
type: string
fips:
default: false
description: FIPS configures https://www.nist.gov/itl/fips-general-information
Expand Down
4 changes: 4 additions & 0 deletions pkg/asset/installconfig/platformpermscheck.go
Expand Up @@ -39,6 +39,10 @@ func (a *PlatformPermsCheck) Generate(dependencies asset.Parents) error {
ic := &InstallConfig{}
dependencies.Get(ic)

if ic.Config.CredentialsMode != "" {
return nil
}

var err error
platform := ic.Config.Platform.Name()
switch platform {
Expand Down
7 changes: 7 additions & 0 deletions pkg/explain/printer_test.go
Expand Up @@ -35,6 +35,13 @@ func Test_PrintFields(t *testing.T) {
controlPlane <object>
ControlPlane is the configuration for the machines that comprise the control plane.

credentialsMode <string>
Valid Values: "","Mint","Passthrough","Manual"
CredentialsMode is used to explicitly set the mode with which CredentialRequests are satisfied.
If this field is set, then the installer will not attempt to query the cloud permissions before attempting installation. If the field is not set or empty, then the installer will perform its normal verification that the credentials provided are sufficient to perform an installation.
There are three possible values for this field, but the valid values are dependent upon the platform being used. "Mint": create new credentials with a subset of the overall permissions for each CredentialsRequest "Passthrough": copy the credentials with all of the overall permissions for each CredentialsRequest "Manual": CredentialsRequests must be handled manually by the user
For each of the following platforms, the field can set to the specified values. For all other platforms, the field must not be set. AWS: "Mint", "Passthrough", "Manual" Azure: "Mint", "Passthrough" GCP: "Mint", "Passthrough"

fips <boolean>
Default: false
FIPS configures https://www.nist.gov/itl/fips-general-information
Expand Down
36 changes: 36 additions & 0 deletions pkg/types/installconfig.go
Expand Up @@ -119,6 +119,25 @@ type InstallConfig struct {
// +kubebuilder:default=false
// +optional
FIPS bool `json:"fips,omitempty"`

// CredentialsMode is used to explicitly set the mode with which CredentialRequests are satisfied.
//
// If this field is set, then the installer will not attempt to query the cloud permissions before attempting
// installation. If the field is not set or empty, then the installer will perform its normal verification that the
// credentials provided are sufficient to perform an installation.
//
// There are three possible values for this field, but the valid values are dependent upon the platform being used.
// "Mint": create new credentials with a subset of the overall permissions for each CredentialsRequest
// "Passthrough": copy the credentials with all of the overall permissions for each CredentialsRequest
// "Manual": CredentialsRequests must be handled manually by the user
//
// For each of the following platforms, the field can set to the specified values. For all other platforms, the
// field must not be set.
// AWS: "Mint", "Passthrough", "Manual"
// Azure: "Mint", "Passthrough"
// GCP: "Mint", "Passthrough"
// +optional
CredentialsMode CredentialsMode `json:"credentialsMode,omitempty"`
}

// ClusterDomain returns the DNS domain that all records for a cluster must belong to.
Expand Down Expand Up @@ -294,3 +313,20 @@ type ImageContentSource struct {
// +optional
Mirrors []string `json:"mirrors,omitempty"`
}

// CredentialsMode is the mode by which CredentialsRequests will be satisfied.
// +kubebuilder:validation:Enum="";Mint;Passthrough;Manual
type CredentialsMode string

const (
// ManualCredentialsMode indicates that cloud-credential-operator should not process any CredentialsRequests.
ManualCredentialsMode CredentialsMode = "Manual"

// MintCredentialsMode indicates that cloud-credential-operator should be creating users for each
// CredentialsRequest.
MintCredentialsMode CredentialsMode = "Mint"

// PassthroughCredentialsMode indicates that cloud-credential-operator should just copy over the cluster's
// cloud credentials for each CredentialsRequest.
PassthroughCredentialsMode CredentialsMode = "Passthrough"
)
28 changes: 28 additions & 0 deletions pkg/types/validation/installconfig.go
Expand Up @@ -9,6 +9,7 @@ import (

dockerref "github.com/containers/image/docker/reference"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"

"github.com/openshift/installer/pkg/ipnet"
Expand Down Expand Up @@ -98,6 +99,7 @@ func ValidateInstallConfig(c *types.InstallConfig, openStackValidValuesFetcher o
if _, ok := validPublishingStrategies[c.Publish]; !ok {
allErrs = append(allErrs, field.NotSupported(field.NewPath("publish"), c.Publish, validPublishingStrategyValues))
}
allErrs = append(allErrs, validateCloudCredentialsMode(c.CredentialsMode, field.NewPath("credentialsMode"), c.Platform.Name())...)

return allErrs
}
Expand Down Expand Up @@ -459,3 +461,29 @@ var (
return v
}()
)

func validateCloudCredentialsMode(mode types.CredentialsMode, fldPath *field.Path, platform string) field.ErrorList {
if mode == "" {
return nil
}
allErrs := field.ErrorList{}
// validPlatformCredentialsModes is a map from the platform name to a slice of credentials modes that are valid
// for the platform. If a platform name is not in the map, then the credentials mode cannot be set for that platform.
validPlatformCredentialsModes := map[string][]types.CredentialsMode{
aws.Name: {types.MintCredentialsMode, types.PassthroughCredentialsMode, types.ManualCredentialsMode},
azure.Name: {types.MintCredentialsMode, types.PassthroughCredentialsMode},
gcp.Name: {types.MintCredentialsMode, types.PassthroughCredentialsMode},
}
if validModes, ok := validPlatformCredentialsModes[platform]; ok {
validModesSet := sets.NewString()
for _, m := range validModes {
validModesSet.Insert(string(m))
}
if !validModesSet.Has(string(mode)) {
allErrs = append(allErrs, field.NotSupported(fldPath, mode, validModesSet.List()))
}
} else {
allErrs = append(allErrs, field.Invalid(fldPath, mode, fmt.Sprintf("cannot be set when using the %q platform", platform)))
}
return allErrs
}
37 changes: 37 additions & 0 deletions pkg/types/validation/installconfig_test.go
Expand Up @@ -933,6 +933,43 @@ func TestValidateInstallConfig(t *testing.T) {
}(),
expectedError: `^compute\[0\].architecture: Invalid value: "ppc64le": heteregeneous multi-arch is not supported; compute pool architecture must match control plane$`,
},
{
name: "valid cloud credentials mode",
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.CredentialsMode = types.PassthroughCredentialsMode
return c
}(),
},
{
name: "unsupported manual cloud credentials mode",
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.Platform = types.Platform{GCP: validGCPPlatform()}
c.CredentialsMode = types.ManualCredentialsMode
return c
}(),
expectedError: `^credentialsMode: Unsupported value: "Manual": supported values: "Mint", "Passthrough"$`,
},
{
name: "invalidly set cloud credentials mode",
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.Platform = types.Platform{BareMetal: validBareMetalPlatform()}
c.CredentialsMode = types.PassthroughCredentialsMode
return c
}(),
expectedError: `^credentialsMode: Invalid value: "Passthrough": cannot be set when using the "baremetal" platform$`,
},
{
name: "bad cloud credentials mode",
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.CredentialsMode = "bad-mode"
return c
}(),
expectedError: `^credentialsMode: Unsupported value: "bad-mode": supported values: "Manual", "Mint", "Passthrough"$`,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
Expand Down