Skip to content

Commit

Permalink
Added s3 bucket policy CR, controller and client
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 5, 2020
1 parent 383af19 commit 05f3957
Show file tree
Hide file tree
Showing 31 changed files with 1,272 additions and 1,066 deletions.
2 changes: 2 additions & 0 deletions apis/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
identityv1alpha1 "github.com/crossplane/provider-aws/apis/identity/v1alpha1"
identityv1beta1 "github.com/crossplane/provider-aws/apis/identity/v1beta1"
networkv1alpha3 "github.com/crossplane/provider-aws/apis/network/v1alpha3"
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 @@ -44,6 +45,7 @@ func init() {
networkv1alpha3.SchemeBuilder.AddToScheme,
awsv1alpha3.SchemeBuilder.AddToScheme,
storagev1alpha3.SchemeBuilder.AddToScheme,
storagev1alpha1.SchemeBuilder.AddToScheme,
databasev1alpha1.SchemeBuilder.AddToScheme,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha3
package v1alpha1

import (
"encoding/json"

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

runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
Expand All @@ -27,87 +25,165 @@ import (
// S3BucketPolicyParameters define the desired state of an AWS S3BucketPolicy.
type S3BucketPolicyParameters struct {
// This is the current IAM policy version
PolicyVersion string `json:"Version"`
PolicyVersion string `json:"version"`

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

// This is the list of statement this policy applies
PolicyStatement []S3BucketPolicyStatement `json:"Statement"`
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"`
}

// 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"`
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"`
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"`
Principal *S3BucketPrincipal `json:"principal,omitempty"`

// Each element of the PolicyAction array describes describes the specific
// 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"`
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.
ApplyToIAMUser bool `json:"EffectIAMUser,omitempty"`
// 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"`
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"`
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"`
AWSPrincipal []string `json:"aws,omitempty"`
}

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

//MarshalJSON is the custom marshaller for the S3BucketPrincipal
func (p *S3BucketPrincipal) MarshalJSON() ([]byte, error) {
// Serialize is the custom serializer for the S3BucketPrincipal
func (p *S3BucketPrincipal) Serialize() (interface{}, error) {
all := "*"
if p.AllowAnon {
return json.Marshal("*")
return all, nil
}
m := make(map[string][]string)
m["AWS"] = p.AWSPrincipal
return json.Marshal(m)
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"`
ForProvider S3BucketPolicyParameters `json:"forProvider"`
// 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"`

// A flag to signify if the bucket has been created already
Created bool `json:"-"`
PolicyBody S3BucketPolicyParameters `json:"forProvider"`
}

// An S3BucketPolicyStatus represents the observed state of an
Expand All @@ -118,10 +194,10 @@ type S3BucketPolicyStatus struct {

// +kubebuilder:object:root=true

// An S3BucketPolicy is a managed resource that represents an AWS IAM
// User policy attachment.
// +kubebuilder:printcolumn:name="USERNAME",type="string",JSONPath=".spec.forProvider.userName"
// +kubebuilder:printcolumn:name="POLICYARN",type="string",JSONPath=".spec.forProvider.policyArn"
// An S3BucketPolicy is a managed resource that represents an AWS Bucket
// policy.
// +kubebuilder:printcolumn:name="USERNAME",type="string",JSONPath=".spec.userName"
// +kubebuilder:printcolumn:name="BUCKETNAME",type="string",JSONPath=".spec.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"
Expand Down
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha3
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"
Expand All @@ -24,7 +26,7 @@ import (
// S3BucketIAMUser returns the Spec.UserName of a S3Bucket.
func S3BucketIAMUser() reference.ExtractValueFn {
return func(mg resource.Managed) string {
r, ok := mg.(*S3Bucket)
r, ok := mg.(*v1alpha3.S3Bucket)
if !ok {
return ""
}
Expand All @@ -35,33 +37,32 @@ func S3BucketIAMUser() reference.ExtractValueFn {
// ResolveReferences of this S3BucketPolicy
func (mg *S3BucketPolicy) ResolveReferences(ctx context.Context, c client.Reader) error {
r := reference.NewAPIResolver(c, mg)

// Resolve spec.forProvider.BucketName
// Resolve spec.BucketName
rsp, err := r.Resolve(ctx, reference.ResolutionRequest{
CurrentValue: reference.FromPtrValue(mg.Spec.BucketName),
Reference: mg.Spec.BucketNameRef,
Selector: mg.Spec.BucketNameSelector,
To: reference.To{Managed: &S3Bucket{}, List: &S3BucketList{}},
CurrentValue: 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.BucketName = reference.ToPtrValue(rsp.ResolvedValue)
mg.Spec.BucketNameRef = rsp.ResolvedReference
mg.Spec.PolicyBody.BucketName = rsp.ResolvedValue
mg.Spec.PolicyBody.BucketNameRef = rsp.ResolvedReference

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

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 05f3957

Please sign in to comment.