Merge pull request #15726 from johngmyers/asset-acl

Don't set object-level public ACL in S3 FileRepository
This commit is contained in:
Kubernetes Prow Robot 2023-08-12 20:53:19 -07:00 committed by GitHub
commit ca1dd07fc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 8 additions and 179 deletions

View File

@ -32,7 +32,6 @@ import (
"k8s.io/klog/v2"
channelscmd "k8s.io/kops/channels/pkg/cmd"
gceacls "k8s.io/kops/pkg/acls/gce"
s3acls "k8s.io/kops/pkg/acls/s3"
kopsclient "k8s.io/kops/pkg/client/clientset_generated/clientset"
"k8s.io/kops/pkg/client/simple"
"k8s.io/kops/pkg/client/simple/api"
@ -60,7 +59,6 @@ type Factory struct {
func NewFactory(options *FactoryOptions) *Factory {
gceacls.Register()
s3acls.Register()
return &Factory{
options: options,

View File

@ -41,6 +41,10 @@ spec:
fileRepository: https://example.com/files
```
The repository must allow nodes to perform unauthenticated reads. The repository can
be public or it can allow read access through network connectivity, such as access
through a particular AWS Endpoint.
## Copying assets into repositories
{{ kops_feature_table(kops_added_default='1.22') }}

View File

@ -16,6 +16,10 @@ This is a document to gather the release notes prior to the release.
# Breaking changes
## AWS
* The `kops get assets --copy` command no longer sets object-level public-read ACLs in the destination fileRDoepository.
## Other breaking changes
* Support for Kubernetes version 1.22 has been removed.

View File

@ -1,89 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package s3
import (
"context"
"fmt"
"net/url"
"strings"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/acls"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/values"
"k8s.io/kops/util/pkg/vfs"
)
// s3PublicAclStrategy is the AclStrategy for objects that are written with public read only ACL.
// This strategy is used by custom file assets.
type s3PublicAclStrategy struct{}
var _ acls.ACLStrategy = &s3PublicAclStrategy{}
// GetACL creates a s3PublicAclStrategy object for writing public files with assets FileRepository.
// This strategy checks if the files are inside the state store, and if the files are located inside
// the state store, this returns nil and logs a message (level 8) that it will not run.
func (s *s3PublicAclStrategy) GetACL(ctx context.Context, p vfs.Path, cluster *kops.Cluster) (vfs.ACL, error) {
if cluster.Spec.Assets == nil || cluster.Spec.Assets.FileRepository == nil {
return nil, nil
}
s3Path, ok := p.(*vfs.S3Path)
if !ok {
return nil, nil
}
fileRepository := values.StringValue(cluster.Spec.Assets.FileRepository)
u, err := url.Parse(fileRepository)
if err != nil {
return "", fmt.Errorf("unable to parse: %q", fileRepository)
}
// We are checking that the file repository url is in S3
_, err = vfs.VFSPath(fileRepository)
if err != nil {
klog.V(8).Infof("path %q is not inside of a s3 bucket", u.String())
return nil, nil
}
config, err := url.Parse(cluster.Spec.ConfigStore.Base)
if err != nil {
return "", fmt.Errorf("unable to parse: %q", cluster.Spec.ConfigStore.Base)
}
// We are checking that the path defined is not the state store, if it is
// we do NOT set the state store as public read.
if strings.Contains(u.Path, config.Path) {
klog.V(8).Infof("path %q is inside of config store %q, not setting public-read acl", u.Path, config.Path)
return nil, nil
}
if strings.TrimPrefix(u.Path, "/") == s3Path.Bucket() {
return &vfs.S3Acl{
RequestACL: values.String("public-read"),
}, nil
}
klog.V(8).Infof("path %q is not inside the file registry %q, not setting public-read acl", u.Path, config.Path)
return nil, nil
}
func Register() {
acls.RegisterPlugin("k8s.io/kops/acl/s3", &s3PublicAclStrategy{})
}

View File

@ -1,88 +0,0 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package s3
import (
"context"
"testing"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/values"
"k8s.io/kops/util/pkg/vfs"
)
func Test_Strategy(t *testing.T) {
ctx := context.TODO()
context := &vfs.VFSContext{}
path, err := context.BuildVfsPath("s3://test/foo")
if err != nil {
t.Errorf("unable to create path: %v", err)
}
cluster := &kops.Cluster{
Spec: kops.ClusterSpec{
ConfigStore: kops.ConfigStoreSpec{
Base: "s3://my_state_store/cluster",
},
Assets: &kops.AssetsSpec{
FileRepository: values.String("https://s3.amazonaws.com/test"),
},
},
}
s := &s3PublicAclStrategy{}
acl, err := s.GetACL(ctx, path, cluster)
if err != nil {
t.Errorf("error getting ACL: %v", err)
}
if acl == nil {
t.Errorf("public ro ACL is nil and should not be, this test is a positive test case.")
}
}
func Test_In_StateStore(t *testing.T) {
ctx := context.TODO()
context := &vfs.VFSContext{}
stateStore, err := context.BuildVfsPath("s3://my_state_store/cluster")
if err != nil {
t.Errorf("unable to create path: %v", err)
}
cluster := &kops.Cluster{
Spec: kops.ClusterSpec{
ConfigStore: kops.ConfigStoreSpec{
Base: "s3://my_state_store/cluster",
},
Assets: &kops.AssetsSpec{
FileRepository: values.String("https://s3.amazonaws.com/my_state_store/opps"),
},
},
}
s := &s3PublicAclStrategy{}
acl, err := s.GetACL(ctx, stateStore, cluster)
if err != nil {
t.Errorf("error getting ACL: %v", err)
}
if acl != nil {
t.Errorf("public ro ACL is set but path is in the state store, this test is a negative test case.")
}
}