Skip to content

Commit

Permalink
added S3BucketPolicy CR
Browse files Browse the repository at this point in the history
Signed-off-by: Krish Chowdhary <krish@redhat.com>
  • Loading branch information
krishchow committed Aug 10, 2020
1 parent 0187f39 commit 9e59da3
Show file tree
Hide file tree
Showing 16 changed files with 1,923 additions and 3 deletions.
2 changes: 2 additions & 0 deletions apis/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
notificationv1alpha3 "github.com/crossplane/provider-aws/apis/notification/v1alpha1"
redshiftv1alpha1 "github.com/crossplane/provider-aws/apis/redshift/v1alpha1"
route53v1alpha1 "github.com/crossplane/provider-aws/apis/route53/v1alpha1"
storagev1alpha1 "github.com/crossplane/provider-aws/apis/storage/v1alpha1"
storagev1alpha3 "github.com/crossplane/provider-aws/apis/storage/v1alpha3"
awsv1alpha3 "github.com/crossplane/provider-aws/apis/v1alpha3"
)
Expand All @@ -58,6 +59,7 @@ func init() {
ec2v1alpha4.SchemeBuilder.AddToScheme,
awsv1alpha3.SchemeBuilder.AddToScheme,
acmv1alpha1.SchemeBuilder.AddToScheme,
storagev1alpha1.SchemeBuilder.AddToScheme,
storagev1alpha3.SchemeBuilder.AddToScheme,
acmpcav1alpha1.SchemeBuilder.AddToScheme,
databasev1alpha1.SchemeBuilder.AddToScheme,
Expand Down
229 changes: 229 additions & 0 deletions apis/storage/v1alpha1/bucketpolicy_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
Copyright 2019 The Crossplane 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 v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
)

// S3BucketPolicyParameters define the desired state of an AWS S3BucketPolicy.
type S3BucketPolicyParameters struct {
// This is the current IAM policy version
PolicyVersion string `json:"version"`

// This is the policy's optional identifier
PolicyID string `json:"id,omitempty"`

// This is the list of statement this policy applies
PolicyStatement []S3BucketPolicyStatement `json:"statement"`

// BucketName presents the name of the bucket.
// +optional
BucketName *string `json:"bucketName,omitempty"`

// BucketNameRef references to an S3Bucket to retrieve its bucketName
// +optional
BucketNameRef *runtimev1alpha1.Reference `json:"bucketNameRef,omitempty"`

// BucketNameSelector selects a reference to an S3Bucket to retrieve its bucketName
// +optional
BucketNameSelector *runtimev1alpha1.Selector `json:"bucketNameSelector,omitempty"`

// UserName presents the name of the bucket.
// +optional
UserName *string `json:"userName,omitempty"`

// UserNameRef references to an S3Bucket to retrieve its userName
// +optional
UserNameRef *runtimev1alpha1.Reference `json:"userNameRef,omitempty"`

// UserNameSelector selects a reference to an S3Bucket to retrieve its userName
// +optional
UserNameSelector *runtimev1alpha1.Selector `json:"userNameSelector,omitempty"`
}

// Serialize is the custom marshaller for the S3BucketPolicyParameters
func (p *S3BucketPolicyParameters) Serialize() (interface{}, error) {
m := make(map[string]interface{})
m["Version"] = p.PolicyVersion
if p.PolicyID != "" {
m["Id"] = p.PolicyID
}
slc := make([]interface{}, len(p.PolicyStatement))
for i, v := range p.PolicyStatement {
msg, err := v.Serialize()
if err != nil {
return nil, err
}
slc[i] = msg
}
m["Statement"] = slc
return m, nil
}

// S3BucketPolicyStatement defines an individual statement within the
// S3BucketPolicyBody
type S3BucketPolicyStatement struct {
// Optional identifier for this statement, must be unique within the
// policy if provided.
StatementID string `json:"sid,omitempty"`

// The effect is required and specifies whether the statement results
// in an allow or an explicit deny. Valid values for Effect are Allow and Deny.
Effect string `json:"effect"`

// Used with the S3 policy to specify the principal that is allowed
// or denied access to a resource.
Principal *S3BucketPrincipal `json:"principal,omitempty"`

// Used with the S3 policy to specify the users which are not included
// in this policy
NotPrincipal *S3BucketPrincipal `json:"notPrincipal,omitempty"`

// Each element of the PolicyAction array describes the specific
// action or actions that will be allowed or denied with this PolicyStatement.
PolicyAction []string `json:"action,omitempty"`

// Each element of the NotPolicyAction array will allow the property to match
// all but the listed actions.
NotPolicyAction []string `json:"notAction,omitempty"`

// This flag indicates that this policy should apply to the IAMUsername
// that was either passed in or created for this bucket, this user will
// added to the action array
ApplyToIAMUser bool `json:"effectIAMUser,omitempty"`

// The paths on which this resource will apply
ResourcePath []string `json:"resource,omitempty"`

// This will explicitly match all resource paths except the ones
// specified in this array
NotResourcePath []string `json:"notResource,omitempty"`
}

func checkExistsArray(slc []string) bool {
return len(slc) != 0
}

// Serialize is the custom marshaller for the S3BucketPolicyStatement
func (p *S3BucketPolicyStatement) Serialize() (interface{}, error) {
m := make(map[string]interface{})
if p.Principal != nil {
principal, err := p.Principal.Serialize()
if err != nil {
return nil, err
}
m["Principal"] = principal
}
if p.NotPrincipal != nil {
notPrincipal, err := p.NotPrincipal.Serialize()
if err != nil {
return nil, err
}
m["NotPrincipal"] = notPrincipal
}
if checkExistsArray(p.PolicyAction) {
m["Action"] = tryFirst(p.PolicyAction)
}
if checkExistsArray(p.NotPolicyAction) {
m["NotAction"] = tryFirst(p.NotPolicyAction)
}
if checkExistsArray(p.ResourcePath) {
m["Resource"] = tryFirst(p.ResourcePath)
}
if checkExistsArray(p.NotResourcePath) {
m["NotResource"] = tryFirst(p.NotResourcePath)
}
m["Effect"] = p.Effect
if p.StatementID != "" {
m["Sid"] = p.StatementID
}
return m, nil
}

// S3BucketPrincipal defines the principal users affected by
// the S3BucketPolicyStatement
type S3BucketPrincipal struct {
// This flag indicates if the policy should be made available
// to all anonymous users.
AllowAnon bool `json:"allowAnon,omitempty"`

// This list contains the all of the AWS IAM users which are affected
// by the policy statement
AWSPrincipal []string `json:"aws,omitempty"`
}

func tryFirst(slc []string) interface{} {
if len(slc) == 1 {
return slc[0]
}
return slc
}

// Serialize is the custom serializer for the S3BucketPrincipal
func (p *S3BucketPrincipal) Serialize() (interface{}, error) {
all := "*"
if p.AllowAnon {
return all, nil
}
m := make(map[string]interface{})
m["AWS"] = tryFirst(p.AWSPrincipal)
return m, nil
}

// An S3BucketPolicySpec defines the desired state of an
// S3BucketPolicy.
type S3BucketPolicySpec struct {
runtimev1alpha1.ResourceSpec `json:",inline"`
PolicyBody S3BucketPolicyParameters `json:"forProvider"`
}

// An S3BucketPolicyStatus represents the observed state of an
// S3BucketPolicy.
type S3BucketPolicyStatus struct {
runtimev1alpha1.ResourceStatus `json:",inline"`
}

// +kubebuilder:object:root=true

// An S3BucketPolicy is a managed resource that represents an AWS Bucket
// policy.
// +kubebuilder:printcolumn:name="USERNAME",type="string",JSONPath=".spec.forProvider.userName"
// +kubebuilder:printcolumn:name="BUCKETNAME",type="string",JSONPath=".spec.forProvider.bucketName"
// +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status"
// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster
type S3BucketPolicy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec S3BucketPolicySpec `json:"spec"`
Status S3BucketPolicyStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// S3BucketPolicyList contains a list of BucketPolicies
type S3BucketPolicyList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []S3BucketPolicy `json:"items"`
}
22 changes: 22 additions & 0 deletions apis/storage/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
Copyright 2019 The Crossplane 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 v1alpha1 contains configuration resources for AWS storage services such as
// S3.
// +kubebuilder:object:generate=true
// +groupName=storage.aws.crossplane.io
// +versionName=v1alpha1
package v1alpha1
69 changes: 69 additions & 0 deletions apis/storage/v1alpha1/referencers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright 2019 The Crossplane 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 v1alpha1

import (
"context"

"github.com/crossplane/provider-aws/apis/storage/v1alpha3"

"github.com/crossplane/crossplane-runtime/pkg/reference"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// S3BucketIAMUser returns the Spec.UserName of a S3Bucket.
func S3BucketIAMUser() reference.ExtractValueFn {
return func(mg resource.Managed) string {
r, ok := mg.(*v1alpha3.S3Bucket)
if !ok {
return ""
}
return r.Spec.IAMUsername
}
}

// ResolveReferences of this S3BucketPolicy
func (mg *S3BucketPolicy) ResolveReferences(ctx context.Context, c client.Reader) error {
r := reference.NewAPIResolver(c, mg)
// Resolve spec.BucketName
rsp, err := r.Resolve(ctx, reference.ResolutionRequest{
CurrentValue: reference.FromPtrValue(mg.Spec.PolicyBody.BucketName),
Reference: mg.Spec.PolicyBody.BucketNameRef,
Selector: mg.Spec.PolicyBody.BucketNameSelector,
To: reference.To{Managed: &v1alpha3.S3Bucket{}, List: &v1alpha3.S3BucketList{}},
Extract: reference.ExternalName(),
})
if err != nil {
return err
}
mg.Spec.PolicyBody.BucketName = reference.ToPtrValue(rsp.ResolvedValue)
mg.Spec.PolicyBody.BucketNameRef = rsp.ResolvedReference

// Resolve spec.UserName
rsp, err = r.Resolve(ctx, reference.ResolutionRequest{
CurrentValue: reference.FromPtrValue(mg.Spec.PolicyBody.UserName),
Reference: mg.Spec.PolicyBody.UserNameRef,
Selector: mg.Spec.PolicyBody.UserNameSelector,
To: reference.To{Managed: &v1alpha3.S3Bucket{}, List: &v1alpha3.S3BucketList{}},
Extract: S3BucketIAMUser(),
})
if err != nil {
return err
}
mg.Spec.PolicyBody.UserName = reference.ToPtrValue(rsp.ResolvedValue)
mg.Spec.PolicyBody.UserNameRef = rsp.ResolvedReference

return nil
}
50 changes: 50 additions & 0 deletions apis/storage/v1alpha1/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright 2019 The Crossplane 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 v1alpha1

import (
"reflect"

"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)

// Package type metadata.
const (
Group = "storage.aws.crossplane.io"
Version = "v1alpha1"
)

var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version}

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
)

// S3BucketPolicy type metadata.
var (
S3BucketPolicyKind = reflect.TypeOf(S3BucketPolicy{}).Name()
S3BucketPolicyGroupKind = schema.GroupKind{Group: Group, Kind: S3BucketPolicyKind}.String()
S3BucketPolicyKindAPIVersion = S3BucketPolicyKind + "." + SchemeGroupVersion.String()
S3BucketPolicyGroupVersionKind = SchemeGroupVersion.WithKind(S3BucketPolicyKind)
)

func init() {
SchemeBuilder.Register(&S3BucketPolicy{}, &S3BucketPolicyList{})
}
Loading

0 comments on commit 9e59da3

Please sign in to comment.