mirror of https://github.com/kubernetes/kops.git
Merge pull request #16050 from sl1pm4t/gcp-sa-issuer
gce: Add support for publishing Service Account Issuer documents to GCS
This commit is contained in:
commit
a4bd641630
|
|
@ -1485,7 +1485,7 @@ spec:
|
|||
```
|
||||
|
||||
The `discoveryStore` option causes kOps to publish an OIDC-compatible discovery document
|
||||
to a path in an S3 bucket. This would ordinarily be a different bucket than the state store.
|
||||
to a path in an object storage bucket (such as S3 or GCS). This would ordinarily be a different bucket than the state store.
|
||||
kOps will automatically configure `spec.kubeAPIServer.serviceAccountIssuer` and default
|
||||
`spec.kubeAPIServer.serviceAccountJWKSURI` to the corresponding
|
||||
HTTPS URL.
|
||||
|
|
|
|||
|
|
@ -220,6 +220,8 @@ func validateServiceAccountIssuerDiscovery(c *kops.Cluster, said *kops.ServiceAc
|
|||
if strings.Contains(base.Bucket(), ".") {
|
||||
allErrs = append(allErrs, field.Invalid(saidStoreField, saidStore, "Bucket name cannot contain dots"))
|
||||
}
|
||||
case *vfs.GSPath:
|
||||
// No known restrictions currently. Added here to avoid falling into the default catch all below.
|
||||
case *vfs.MemFSPath:
|
||||
// memfs is ok for tests; not OK otherwise
|
||||
if !base.IsClusterReadable() {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,11 @@ func (b *DiscoveryOptionsBuilder) BuildOptions(o interface{}) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case *vfs.GSPath:
|
||||
serviceAccountIssuer, err = base.GetHTTPsUrl()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case *vfs.MemFSPath:
|
||||
if !base.IsClusterReadable() {
|
||||
// If this _is_ a test, we should call MarkClusterReadable
|
||||
|
|
|
|||
|
|
@ -104,6 +104,24 @@ func (b *IssuerDiscoveryModelBuilder) Build(c *fi.CloudupModelBuilderContext) er
|
|||
} else {
|
||||
klog.Infof("using user managed serviceAccountIssuers")
|
||||
}
|
||||
case *vfs.GSPath:
|
||||
discoveryStoreURL, err := discoveryStore.GetHTTPsUrl()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if discoveryStoreURL == fi.ValueOf(b.Cluster.Spec.KubeAPIServer.ServiceAccountIssuer) {
|
||||
// Using Google Cloud Storage requires public access
|
||||
isPublic, err := discoveryStore.IsBucketPublic(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("checking if bucket was public: %w", err)
|
||||
}
|
||||
if !isPublic {
|
||||
klog.Infof("serviceAccountIssuers bucket %q is not public; will use object ACL", discoveryStore.Bucket())
|
||||
publicFileACL = fi.PtrTo(true)
|
||||
}
|
||||
} else {
|
||||
klog.Infof("using user managed serviceAccountIssuers")
|
||||
}
|
||||
|
||||
case *vfs.MemFSPath:
|
||||
// ok
|
||||
|
|
|
|||
|
|
@ -417,6 +417,46 @@ func (p *GSPath) Hash(a hashing.HashAlgorithm) (*hashing.Hash, error) {
|
|||
return &hashing.Hash{Algorithm: hashing.HashAlgorithmMD5, HashValue: md5Bytes}, nil
|
||||
}
|
||||
|
||||
func (p *GSPath) GetHTTPsUrl() (string, error) {
|
||||
url := fmt.Sprintf("https://storage.googleapis.com/%s/%s", p.bucket, p.key)
|
||||
return strings.TrimSuffix(url, "/"), nil
|
||||
}
|
||||
|
||||
func (p *GSPath) IsBucketPublic(ctx context.Context) (bool, error) {
|
||||
client, err := p.Client(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
bucket, err := client.Buckets.Get(p.bucket).Do()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check bucket has uniform bucket-level IAM
|
||||
if !bucket.IamConfiguration.BucketPolicyOnly.Enabled {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Check `allUsers` IAM has `roles/storage.objectViewer` permission
|
||||
policy, err := client.Buckets.GetIamPolicy(p.bucket).Do()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, binding := range policy.Bindings {
|
||||
if binding.Role == "roles/storage.objectViewer" {
|
||||
for _, member := range binding.Members {
|
||||
if member == "allUsers" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
type terraformGSObject struct {
|
||||
Bucket string `json:"bucket" cty:"bucket"`
|
||||
Name string `json:"name" cty:"name"`
|
||||
|
|
|
|||
Loading…
Reference in New Issue