Skip to content

Commit

Permalink
fix: implement both ECR auth methods
Browse files Browse the repository at this point in the history
A new change was released last week that changed the SCHEMA of an ECR
Integration, a new required field named `AWS_AUTH_TYPE` was added that
broke our integrations, this is the fix for such bug.

Additionally, we have implemented both authentication methods, IAM Role
and Access Key.

JIRA: ALLY-371

Signed-off-by: Salim Afiune Maya <[email protected]>
  • Loading branch information
afiune committed Mar 10, 2021
1 parent ed8f7f0 commit 7af312c
Show file tree
Hide file tree
Showing 10 changed files with 387 additions and 127 deletions.
6 changes: 3 additions & 3 deletions api/integrations_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
// aws := api.NewAwsIntegration("foo",
// api.AwsCfgIntegration,
// api.AwsIntegrationData{
// Credentials: api.AwsIntegrationCreds {
// Credentials: api.AwsCrossAccountCreds {
// RoleArn: "arn:aws:XYZ",
// ExternalID: "1",
// },
Expand Down Expand Up @@ -131,7 +131,7 @@ type AwsIntegration struct {
}

type AwsIntegrationData struct {
Credentials AwsIntegrationCreds `json:"CROSS_ACCOUNT_CREDENTIALS" mapstructure:"CROSS_ACCOUNT_CREDENTIALS"`
Credentials AwsCrossAccountCreds `json:"CROSS_ACCOUNT_CREDENTIALS" mapstructure:"CROSS_ACCOUNT_CREDENTIALS"`

// QueueUrl is a field that exists and is required for the AWS_CT_SQS integration,
// though, it doesn't exist for AWS_CFG integrations, that's why we omit it if empty
Expand Down Expand Up @@ -169,7 +169,7 @@ func (aws *AwsIntegrationData) DecodeAccountMappingFile() ([]byte, error) {
return raw, nil
}

type AwsIntegrationCreds struct {
type AwsCrossAccountCreds struct {
RoleArn string `json:"ROLE_ARN" mapstructure:"ROLE_ARN"`
ExternalID string `json:"EXTERNAL_ID" mapstructure:"EXTERNAL_ID"`
}
8 changes: 4 additions & 4 deletions api/integrations_aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
func TestIntegrationsNewAwsCfgIntegration(t *testing.T) {
subject := api.NewAwsCfgIntegration("integration_name",
api.AwsIntegrationData{
Credentials: api.AwsIntegrationCreds{
Credentials: api.AwsCrossAccountCreds{
RoleArn: "arn:foo:bar",
ExternalID: "0123456789",
},
Expand Down Expand Up @@ -62,7 +62,7 @@ func TestIntegrationsNewAwsCfgIntegrationWithCustomTemplateFile(t *testing.T) {
}
}`)
awsData := api.AwsIntegrationData{
Credentials: api.AwsIntegrationCreds{
Credentials: api.AwsCrossAccountCreds{
RoleArn: "arn:foo:bar",
ExternalID: "0123456789",
},
Expand Down Expand Up @@ -120,7 +120,7 @@ func TestIntegrationsCreateAws(t *testing.T) {
data := api.NewAwsIntegration("integration_name",
api.AwsCfgIntegration,
api.AwsIntegrationData{
Credentials: api.AwsIntegrationCreds{
Credentials: api.AwsCrossAccountCreds{
RoleArn: "arn:foo:bar",
ExternalID: "0123456789",
},
Expand Down Expand Up @@ -208,7 +208,7 @@ func TestIntegrationsUpdateAws(t *testing.T) {
data := api.NewAwsIntegration("integration_name",
api.AwsCloudTrailIntegration,
api.AwsIntegrationData{
Credentials: api.AwsIntegrationCreds{
Credentials: api.AwsCrossAccountCreds{
RoleArn: "arn:foo:bar",
ExternalID: "0123456789",
},
Expand Down
86 changes: 0 additions & 86 deletions api/integrations_ctr_reg_ecr.go

This file was deleted.

95 changes: 95 additions & 0 deletions api/integrations_ctr_reg_ecr_access_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//
// Author:: Salim Afiune Maya (<[email protected]>)
// Copyright:: Copyright 2020, Lacework Inc.
// License:: Apache License, Version 2.0
//
// 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 api

// This file has the abstraction of the Lacework APIs to manage integrations
// of type AWS_ECR using ACCESS_KEY_CREDENTIALS as Authentication Method

func NewAwsEcrWithAccessKeyIntegration(name string, data AwsEcrDataWithAccessKeyCreds) AwsEcrWithAccessKeyIntegration {
data.RegistryType = EcrRegistry.String()
data.AwsAuthType = AwsEcrAccessKey.String()
return AwsEcrWithAccessKeyIntegration{
commonIntegrationData: commonIntegrationData{
Name: name,
Type: ContainerRegistryIntegration.String(),
Enabled: 1,
},
Data: data,
}
}

// CreateAwsEcrWithAccessKey creates an AWS_ECR integration using an AWS Access
// Key as authenticatin method to access the registry
func (svc *IntegrationsService) CreateAwsEcrWithAccessKey(integration AwsEcrWithAccessKeyIntegration) (
response AwsEcrWithAccessKeyIntegrationResponse,
err error,
) {
err = svc.create(integration, &response)
return
}

// GetAwsEcrWithAccessKey gets an AWS_ECR integration that matches with
// the provided integration guid on the Lacework Server
func (svc *IntegrationsService) GetAwsEcrWithAccessKey(guid string) (
response AwsEcrWithAccessKeyIntegrationResponse,
err error,
) {
err = svc.get(guid, &response)
return
}

// UpdateAwsEcrWithAccessKey updates a single AWS_ECR integration
func (svc *IntegrationsService) UpdateAwsEcrWithAccessKey(integration AwsEcrWithAccessKeyIntegration) (
response AwsEcrWithAccessKeyIntegrationResponse,
err error,
) {
err = svc.update(integration.IntgGuid, integration, &response)
return
}

type AwsEcrCommonData struct {
AwsAuthType string `json:"AWS_AUTH_TYPE" mapstructure:"AWS_AUTH_TYPE"`
RegistryType string `json:"REGISTRY_TYPE" mapstructure:"REGISTRY_TYPE"`
RegistryDomain string `json:"REGISTRY_DOMAIN" mapstructure:"REGISTRY_DOMAIN"`
LimitByTag string `json:"LIMIT_BY_TAG" mapstructure:"LIMIT_BY_TAG"`
LimitByLabel string `json:"LIMIT_BY_LABEL" mapstructure:"LIMIT_BY_LABEL"`
LimitByRep string `json:"LIMIT_BY_REP,omitempty" mapstructure:"LIMIT_BY_REP"`
LimitNumImg int `json:"LIMIT_NUM_IMG,omitempty" mapstructure:"LIMIT_NUM_IMG"`
}

type AwsEcrWithAccessKeyIntegrationResponse struct {
Data []AwsEcrWithAccessKeyIntegration `json:"data"`
Ok bool `json:"ok"`
Message string `json:"message"`
}

type AwsEcrWithAccessKeyIntegration struct {
commonIntegrationData
Data AwsEcrDataWithAccessKeyCreds `json:"DATA"`
}

type AwsEcrDataWithAccessKeyCreds struct {
Credentials AwsEcrAccessKeyCreds `json:"ACCESS_KEY_CREDENTIALS" mapstructure:"ACCESS_KEY_CREDENTIALS"`
AwsEcrCommonData
}

type AwsEcrAccessKeyCreds struct {
AccessKeyID string `json:"ACCESS_KEY_ID" mapstructure:"ACCESS_KEY_ID"`
SecretAccessKey string `json:"SECRET_ACCESS_KEY" mapstructure:"SECRET_ACCESS_KEY"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ import (
"github.com/stretchr/testify/assert"
)

func TestIntegrationsNewAwsEcrRegistryIntegration(t *testing.T) {
subject := api.NewAwsEcrRegistryIntegration("integration_name",
api.AwsEcrData{
Credentials: api.AwsEcrCreds{
func TestIntegrationsNewAwsEcrAccessKeyIntegration(t *testing.T) {
subject := api.NewAwsEcrWithAccessKeyIntegration("integration_name",
api.AwsEcrDataWithAccessKeyCreds{
Credentials: api.AwsEcrAccessKeyCreds{
AccessKeyID: "id",
SecretAccessKey: "secret",
},
},
)
assert.Equal(t, api.ContainerRegistryIntegration.String(), subject.Type)
assert.Equal(t, api.EcrRegistry.String(), subject.Data.RegistryType)
assert.Equal(t, api.AwsEcrAccessKey.String(), subject.Data.AwsAuthType)
}
98 changes: 98 additions & 0 deletions api/integrations_ctr_reg_ecr_cross_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// Author:: Salim Afiune Maya (<[email protected]>)
// Copyright:: Copyright 2021, Lacework Inc.
// License:: Apache License, Version 2.0
//
// 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 api

// This file has the abstraction of the Lacework APIs to manage integrations
// of type AWS_ECR using CROSS_ACCOUNT_CREDENTIALS as Authentication Method

type ecrAuthType int

const (
AwsEcrIAM ecrAuthType = iota
AwsEcrAccessKey
)

// AwsEcrAuthTypes is the list of available ECR auth types
var AwsEcrAuthTypes = map[ecrAuthType]string{
AwsEcrIAM: "AWS_IAM",
AwsEcrAccessKey: "AWS_ACCESS_KEY",
}

// String returns the string representation of an ECR auth type
func (i ecrAuthType) String() string {
return AwsEcrAuthTypes[i]
}

func NewAwsEcrWithCrossAccountIntegration(name string, data AwsEcrDataWithCrossAccountCreds) AwsEcrWithCrossAccountIntegration {
data.RegistryType = EcrRegistry.String()
data.AwsAuthType = AwsEcrIAM.String()
return AwsEcrWithCrossAccountIntegration{
commonIntegrationData: commonIntegrationData{
Name: name,
Type: ContainerRegistryIntegration.String(),
Enabled: 1,
},
Data: data,
}
}

// CreateAwsEcrWithCrossAccount creates an AWS_ECR integration using an IAM Role as
// authenticatin method to access the registry
func (svc *IntegrationsService) CreateAwsEcrWithCrossAccount(integration AwsEcrWithCrossAccountIntegration) (
response AwsEcrWithCrossAccountIntegrationResponse,
err error,
) {
err = svc.create(integration, &response)
return
}

// GetAwsEcrWithCrossAccount gets an AWS_ECR integration that matches with
// the provided integration guid on the Lacework Server
func (svc *IntegrationsService) GetAwsEcrWithCrossAccount(guid string) (
response AwsEcrWithCrossAccountIntegrationResponse,
err error,
) {
err = svc.get(guid, &response)
return
}

// UpdateAwsEcrWithCrossAccount updates a single AWS_ECR integration
func (svc *IntegrationsService) UpdateAwsEcrWithCrossAccount(integration AwsEcrWithCrossAccountIntegration) (
response AwsEcrWithCrossAccountIntegrationResponse,
err error,
) {
err = svc.update(integration.IntgGuid, integration, &response)
return
}

type AwsEcrWithCrossAccountIntegrationResponse struct {
Data []AwsEcrWithCrossAccountIntegration `json:"data"`
Ok bool `json:"ok"`
Message string `json:"message"`
}

type AwsEcrWithCrossAccountIntegration struct {
commonIntegrationData
Data AwsEcrDataWithCrossAccountCreds `json:"DATA"`
}

type AwsEcrDataWithCrossAccountCreds struct {
Credentials AwsCrossAccountCreds `json:"CROSS_ACCOUNT_CREDENTIALS" mapstructure:"CROSS_ACCOUNT_CREDENTIALS"`
AwsEcrCommonData
}
Loading

0 comments on commit 7af312c

Please sign in to comment.