Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create ACO Admin Task (Lambda and Workflows) #1043

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/admin-create-aco-dev-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Admin Create ACO dev deploy

on:
workflow_call:
workflow_dispatch:
push:
branches:
- austin/BCDA-8629-create-aco-wf
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once all changes are done this should change to 'main'

paths:
- bcda/lambda/admin_create_aco/**
- .github/workflows/admin-create-aco-dev-deploy.yml

jobs:
test:
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
defaults:
run:
working-directory: bcda
environment: dev
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- name: Build admin_create_aco zip file
env:
CGO_ENABLED: 0
run: |
pwd
go build -o bin/bootstrap ./lambda/admin_create_aco/*.go
zip -j function.zip bin/bootstrap
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: arn:aws:iam::${{ secrets.ACCOUNT_ID }}:role/delegatedadmin/developer/bcda-dev-github-actions
- name: Upload and reload
run: |
aws s3 cp --no-progress function.zip \
s3://bcda-dev-admin-create-aco-function/function-${{ github.sha }}.zip
aws lambda update-function-code --function-name bcda-dev-admin-create-aco \
--s3-bucket bcda-dev-admin-create-aco-function --s3-key function-${{ github.sha }}.zip
24 changes: 24 additions & 0 deletions .github/workflows/admin-create-aco-prod-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Admin Create ACO prod deploy
austincanada marked this conversation as resolved.
Show resolved Hide resolved

on:
workflow_dispatch:

jobs:
deploy:
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
environment: prod
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: arn:aws:iam::${{ secrets.ACCOUNT_ID }}:role/delegatedadmin/developer/bcda-prod-github-actions
- name: Promote lambda code from test to prod
run: |
aws s3 cp --no-progress \
s3://bcda-test-admin-create-aco-function/function-${{ github.sha }}.zip \
s3://bcda-prod-admin-create-aco-function/function-${{ github.sha }}.zip
aws lambda update-function-code --function-name bcda-prod-admin-create-aco \
--s3-bucket bcda-prod-admin-create-aco-function --s3-key function-${{ github.sha }}.zip
24 changes: 24 additions & 0 deletions .github/workflows/admin-create-aco-sbx-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Admin Create ACO sbx deploy

on:
workflow_dispatch:

jobs:
deploy:
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
environment: sbx
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: arn:aws:iam::${{ secrets.ACCOUNT_ID }}:role/delegatedadmin/developer/bcda-sbx-github-actions
- name: Promote lambda code from test to sbx
run: |
aws s3 cp --no-progress \
s3://bcda-test-admin-create-aco-function/function-${{ github.sha }}.zip \
s3://bcda-sbx-admin-create-aco-function/function-${{ github.sha }}.zip
aws lambda update-function-code --function-name bcda-sbx-admin-create-aco \
--s3-bucket bcda-sbx-admin-create-aco-function --s3-key function-${{ github.sha }}.zip
35 changes: 35 additions & 0 deletions .github/workflows/admin-create-aco-test-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Admin Create ACO Test Deploy

on:
workflow_call:
workflow_dispatch:

jobs:
test:
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
defaults:
run:
working-directory: bcda
environment: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- name: Build Admin Create ACO zip file
env:
CGO_ENABLED: 0
run: |
go build -o bin/bootstrap ./lambda/admin_create_aco/*.go
zip -j function.zip bin/bootstrap
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: arn:aws:iam::${{ secrets.ACCOUNT_ID }}:role/delegatedadmin/developer/bcda-test-github-actions
- name: Upload and reload
run: |
aws s3 cp --no-progress function.zip \
s3://bcda-test-admin-create-aco-function/function-${{ github.sha }}.zip
aws lambda update-function-code --function-name bcda-test-admin-create-aco \
--s3-bucket bcda-test-admin-create-aco-function --s3-key function-${{ github.sha }}.zip
52 changes: 52 additions & 0 deletions .github/workflows/admin-create-aco-test-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Admin Create ACO Integration Tests

on:
pull_request:
paths:
- .github/workflows/admin-create-aco-test-integration.yml
- .github/workflows/admin-create-aco-dev-deploy.yml
- .github/workflows/admin-create-aco-test-deploy.yml
- .github/workflows/admin-create-aco-sbx-deploy.yml
- .github/workflows/admin-create-aco-prod-deploy.yml
- bcda/lambda/admin_create_aco/**
workflow_dispatch:

# Ensure we have only one integration test running at a time
concurrency:
group: admin-create-aco-integration-test

jobs:
# Deploy first if triggered by pull_request
deploy:
if: ${{ github.event_name == 'pull_request' }}
uses: ./.github/workflows/admin-create-aco-dev-deploy.yml
secrets: inherit

trigger:
if: ${{ always() }}
needs: deploy
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./bcda/lambda/admin_create_aco
outputs:
start_time: ${{ steps.invoke-lambda.outputs.STARTTIME }}
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: arn:aws:iam::${{ secrets.ACCOUNT_ID }}:role/delegatedadmin/developer/bcda-dev-github-actions
- name: Send event to trigger lambda function
id: invoke-lambda
run: |
echo "STARTTIME=`date +%s`" >> "$GITHUB_OUTPUT"
aws lambda invoke --function-name bcda-dev-admin-create-aco \
--cli-binary-format raw-in-base64-out \
--payload '{"name":"Test ACO","cms_id":"testcms"}' test-result.txt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be creating the same ACO each time its called. Do we need to do some kind of clean up? What happens when we call create ACO with an existing ACO by that name/cms_id?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point; do we want to add a cleanupACO type function in this lambda where the removal occurs? We could potentially configure it by saying that if it's running in a non-prod env, then run the cleanup afterwards?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking into it currently.

- name: Verify result
run: |
if grep -q "errorType" test-result.txt; then cat test-result.txt; exit 1; else echo "Success"; fi
14 changes: 8 additions & 6 deletions bcda/bcdacli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
"syscall"
"time"

"github.com/ccoveille/go-safecast"
safecast "github.com/ccoveille/go-safecast"

"github.com/CMSgov/bcda-app/bcda/alr/csv"
"github.com/CMSgov/bcda-app/bcda/alr/gen"
Expand Down Expand Up @@ -47,8 +47,10 @@ import (
)

// App Name and usage. Edit them here to prevent breaking tests
const Name = "bcda"
const Usage = "Beneficiary Claims Data API CLI"
const (
Name = "bcda"
Usage = "Beneficiary Claims Data API CLI"
)

var (
db *sql.DB
Expand All @@ -69,7 +71,7 @@ func setUpApp() *cli.App {
r = postgres.NewRepository(db)
return nil
}
var hours, err = safecast.ToUint(utils.GetEnvInt("FILE_ARCHIVE_THRESHOLD_HR", 72))
hours, err := safecast.ToUint(utils.GetEnvInt("FILE_ARCHIVE_THRESHOLD_HR", 72))
if err != nil {
fmt.Println("Error converting FILE_ARCHIVE_THRESHOLD_HR to uint", err)
}
Expand Down Expand Up @@ -198,7 +200,7 @@ func setUpApp() *cli.App {
},
},
Action: func(c *cli.Context) error {
acoUUID, err := createACO(acoName, acoCMSID)
acoUUID, err := CreateACO(acoName, acoCMSID)
if err != nil {
return err
}
Expand Down Expand Up @@ -698,7 +700,7 @@ func createGroup(id, name, acoID string) (string, error) {
return ssasID, nil
}

func createACO(name, cmsID string) (string, error) {
func CreateACO(name, cmsID string) (string, error) {
if name == "" {
return "", errors.New("ACO name (--name) must be provided")
}
Expand Down
39 changes: 26 additions & 13 deletions bcda/bcdacli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,12 @@ func (s *CLITestSuite) TestIgnoreSignals() {
}

func (s *CLITestSuite) TestGenerateClientCredentials() {
for idx, ips := range [][]string{nil, {testUtils.GetRandomIPV4Address(s.T()), testUtils.GetRandomIPV4Address(s.T())},
{testUtils.GetRandomIPV4Address(s.T())}, nil} {
for idx, ips := range [][]string{
nil,
{testUtils.GetRandomIPV4Address(s.T()), testUtils.GetRandomIPV4Address(s.T())},
{testUtils.GetRandomIPV4Address(s.T())},
nil,
} {
s.T().Run(strconv.Itoa(idx), func(t *testing.T) {
mockArgs := []interface{}{s.testACO.UUID.String(), "", s.testACO.GroupID}
// ips argument is a variadic argument so we need to ensure that the list is expanded
Expand Down Expand Up @@ -178,7 +182,6 @@ func (s *CLITestSuite) TestGenerateClientCredentials_InvalidID() {
}

func (s *CLITestSuite) TestResetSecretCLI() {

// set up the test app writer (to redirect CLI responses from stdout to a byte buffer)
buf := new(bytes.Buffer)
s.testApp.Writer = buf
Expand All @@ -188,8 +191,10 @@ func (s *CLITestSuite) TestResetSecretCLI() {

mock := &auth.MockProvider{}
mock.On("ResetSecret", s.testACO.ClientID).Return(
auth.Credentials{ClientName: *s.testACO.CMSID, ClientID: s.testACO.ClientID,
ClientSecret: uuid.New()},
auth.Credentials{
ClientName: *s.testACO.CMSID, ClientID: s.testACO.ClientID,
ClientSecret: uuid.New(),
},
nil)
auth.SetMockProvider(s.T(), mock)

Expand Down Expand Up @@ -842,14 +847,18 @@ func (s *CLITestSuite) TestDenylistACO() {
notDenylistedCMSID := testUtils.RandomHexID()[0:4]
notFoundCMSID := testUtils.RandomHexID()[0:4]

denylistedACO := models.ACO{UUID: uuid.NewUUID(), CMSID: &denylistedCMSID,
denylistedACO := models.ACO{
UUID: uuid.NewUUID(), CMSID: &denylistedCMSID,
TerminationDetails: &models.Termination{
TerminationDate: time.Date(2020, time.December, 31, 23, 59, 59, 0, time.Local),
CutoffDate: time.Date(2020, time.December, 31, 23, 59, 59, 0, time.Local),
DenylistType: models.Involuntary,
}}
notDenylistedACO := models.ACO{UUID: uuid.NewUUID(), CMSID: &notDenylistedCMSID,
TerminationDetails: nil}
},
}
notDenylistedACO := models.ACO{
UUID: uuid.NewUUID(), CMSID: &notDenylistedCMSID,
TerminationDetails: nil,
}

defer func() {
postgrestest.DeleteACO(s.T(), s.db, denylistedACO.UUID)
Expand Down Expand Up @@ -978,15 +987,19 @@ func (s *CLITestSuite) TestCloneCCLFZips() {

func (s *CLITestSuite) TestGenerateAlrData() {
initialCount := postgrestest.GetALRCount(s.T(), s.db, "A9990")
args := []string{"bcda", "generate-synthetic-alr-data", constants.CMSIDArg, "A9990",
"--alr-template-file", "../alr/gen/testdata/PY21ALRTemplatePrelimProspTable1.csv"}
args := []string{
"bcda", "generate-synthetic-alr-data", constants.CMSIDArg, "A9990",
"--alr-template-file", "../alr/gen/testdata/PY21ALRTemplatePrelimProspTable1.csv",
}
err := s.testApp.Run(args)
assert.NoError(s.T(), err)
assert.Greater(s.T(), postgrestest.GetALRCount(s.T(), s.db, "A9990"), initialCount)

// No CCLF file
err = s.testApp.Run([]string{"bcda", "generate-synthetic-alr-data", constants.CMSIDArg, "UNKNOWN_ACO",
"--alr-template-file", "../alr/gen/testdata/PY21ALRTemplatePrelimProspTable1.csv"})
err = s.testApp.Run([]string{
"bcda", "generate-synthetic-alr-data", constants.CMSIDArg, "UNKNOWN_ACO",
"--alr-template-file", "../alr/gen/testdata/PY21ALRTemplatePrelimProspTable1.csv",
})
assert.EqualError(s.T(), err, "no CCLF8 file found for CMS ID UNKNOWN_ACO")
}

Expand Down
6 changes: 6 additions & 0 deletions bcda/lambda/admin_create_aco/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The Create ACO administrative task lambda will create an ACO and add it to the database. It should be called via AWS's lambda interface (see: <https://confluence.cms.gov/display/BCDA/How+To+deny+an+ACO+From+Generating+Credentials>).

You can run the unit test suite from the base dir (bcda-app) using the following command:

make test-path TEST_PATH="bcda/lambda/admin_create_aco/\*.go". (You might have to make load-fixtures first). It also has an integration test run via github actions (see .github/workflows/admin-create-aco-integration-test.yml).
The lambda is deployed (or promoted in the case of prod) using github actions (see .github/workflows/admin-create-aco-lambda-{env}-deploy.yml files).
Loading
Loading