Skip to content

Commit f5ca6e8

Browse files
Return secret metadata for user (#1604)
1 parent 267e16e commit f5ca6e8

File tree

3 files changed

+69
-18
lines changed

3 files changed

+69
-18
lines changed

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (h Handler) Invoke(ctx context.Context, req []byte) ([]byte, error) {
4747
if strings.Contains(httpRequest.RawPath, "/secrets") {
4848
if httpRequest.RequestContext.HTTP.Method == "GET" {
4949
authHeader := httpRequest.Headers["authorization"]
50-
githubWorkflowSecrets, err := secrets.GetSecrets(httpRequest.QueryStringParameters, authHeader, dynamoDbSvc)
50+
githubWorkflowSecrets, err := secrets.GetSecrets(httpRequest.QueryStringParameters, authHeader, dynamoDbSvc, false)
5151
if err != nil {
5252
response = events.APIGatewayProxyResponse{
5353
StatusCode: http.StatusInternalServerError,

remediation/secrets/secrets.go

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func getClaimsFromAuthToken(authHeader string, skipClaimValidation bool) (*GitHu
148148
return &gitHubWorkflowSecrets, nil
149149
}
150150

151-
func GetSecrets(queryStringParams map[string]string, authHeader string, svc dynamodbiface.DynamoDBAPI) (*GitHubWorkflowSecrets, error) {
151+
func GetSecrets(queryStringParams map[string]string, authHeader string, svc dynamodbiface.DynamoDBAPI, skipValidation bool) (*GitHubWorkflowSecrets, error) {
152152
owner := ""
153153
repo := ""
154154
runId := ""
@@ -158,7 +158,7 @@ func GetSecrets(queryStringParams map[string]string, authHeader string, svc dyna
158158
// this is a call from the GitHub Action
159159
if len(authHeader) > 0 {
160160
// verify OIDC token
161-
gitHubWorkflowSecrets, err = getClaimsFromAuthToken(authHeader, svc == nil) // skip validation for unit tests
161+
gitHubWorkflowSecrets, err = getClaimsFromAuthToken(authHeader, skipValidation) // skip validation for unit tests
162162
if err != nil {
163163
return nil, err
164164
}
@@ -184,25 +184,16 @@ func GetSecrets(queryStringParams map[string]string, authHeader string, svc dyna
184184

185185
// If record exists, check if secrets are set
186186
if gitHubWorkflowSecretsFromDB != nil {
187-
if !authHeaderVerified && gitHubWorkflowSecretsFromDB.AreSecretsSet {
188-
return nil, fmt.Errorf("once secrets are set, they can only be returned to GitHub workflow")
187+
if !authHeaderVerified { // called by user
188+
for i := range gitHubWorkflowSecretsFromDB.Secrets {
189+
// the secret should be cleared. but if not, it should only be returned to the authorized GitHub Action
190+
gitHubWorkflowSecretsFromDB.Secrets[i].Value = ""
191+
}
189192
}
193+
// called by GitHub Action
190194
return gitHubWorkflowSecretsFromDB, nil
191195
}
192196

193-
// If record does not exist, insert record
194-
gitHubWorkflowSecrets.AreSecretsSet = false
195-
secrets := strings.Split(queryStringParams["secrets"], ",")
196-
for _, secret := range secrets {
197-
gitHubWorkflowSecrets.Secrets = append(gitHubWorkflowSecrets.Secrets, Secret{Name: secret, Value: ""})
198-
}
199-
200-
err = setWorkflowSecrets(*gitHubWorkflowSecrets, svc)
201-
202-
if err != nil {
203-
return nil, err
204-
}
205-
206197
return gitHubWorkflowSecrets, nil
207198
}
208199

remediation/secrets/secrets_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,25 @@ import (
44
"reflect"
55
"testing"
66

7+
"github.com/aws/aws-sdk-go/service/dynamodb"
8+
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
9+
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface"
710
"github.com/jarcoal/httpmock"
811
)
912

13+
type mockDynamoDBClient struct {
14+
dynamodbiface.DynamoDBAPI
15+
}
16+
17+
func (m *mockDynamoDBClient) GetItem(input *dynamodb.GetItemInput) (*dynamodb.GetItemOutput, error) {
18+
output := &dynamodb.GetItemOutput{}
19+
gitHubWorkflowSecrets := &GitHubWorkflowSecrets{Repo: "varunsh-coder/actions-playground", RunId: "2800694956",
20+
AreSecretsSet: true, Secrets: []Secret{{Name: "test", Value: "123"}}}
21+
22+
av, _ := dynamodbattribute.MarshalMap(gitHubWorkflowSecrets)
23+
output.Item = av
24+
return output, nil
25+
}
1026
func Test_getClaimsFromAuthToken(t *testing.T) {
1127
type args struct {
1228
authHeader string
@@ -76,3 +92,47 @@ func Test_getSecretsFromString(t *testing.T) {
7692
})
7793
}
7894
}
95+
96+
func TestGetSecrets(t *testing.T) {
97+
type args struct {
98+
queryStringParams map[string]string
99+
authHeader string
100+
svc dynamodbiface.DynamoDBAPI
101+
}
102+
103+
httpmock.Activate()
104+
defer httpmock.DeactivateAndReset()
105+
106+
httpmock.RegisterResponder("GET", "https://token.actions.githubusercontent.com/.well-known/jwks",
107+
httpmock.NewStringResponder(200, `{"keys":[{"n":"4WpHpoBYsVBVfSlfgnRbdPMxP3Eb7rFqE48e4pPM4qH_9EsUZIi21LjOu8UkKn14L4hrRfzfRHG7VQSbxXBU1Qa-xM5yVxdmfQZKBxQnPWaE1v7edjxq1ZYnqHIp90Uvnw6798xMCSvI_V3FR8tix5GaoTgkixXlPc-ozifMyEZMmhvuhfDsSxQeTSHGPlWfGkX0id_gYzKPeI69EGtQ9ZN3PLTdoAI8jxlQ-jyDchi9h2ax6hgMLDsMZyiIXnF2UYq4j36Cs5RgdC296d0hEOHN0WYZE-xPl7y_A9UHcVjrxeGfVOuTBXqjowofimn4ESnVXNReCsOwZCJlvJzfpQ","kty":"RSA","kid":"78167F727DEC5D801DD1C8784C704A1C880EC0E1","alg":"RS256","e":"AQAB","use":"sig","x5c":["MIIDrDCCApSgAwIBAgIQMPdKi0TFTMqmg1HHo6FfsDANBgkqhkiG9w0BAQsFADA2MTQwMgYDVQQDEyt2c3RzLXZzdHNnaHJ0LWdoLXZzby1vYXV0aC52aXN1YWxzdHVkaW8uY29tMB4XDTIyMDEwNTE4NDcyMloXDTI0MDEwNTE4NTcyMlowNjE0MDIGA1UEAxMrdnN0cy12c3RzZ2hydC1naC12c28tb2F1dGgudmlzdWFsc3R1ZGlvLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOFqR6aAWLFQVX0pX4J0W3TzMT9xG+6xahOPHuKTzOKh//RLFGSIttS4zrvFJCp9eC+Ia0X830Rxu1UEm8VwVNUGvsTOclcXZn0GSgcUJz1mhNb+3nY8atWWJ6hyKfdFL58Ou/fMTAkryP1dxUfLYseRmqE4JIsV5T3PqM4nzMhGTJob7oXw7EsUHk0hxj5VnxpF9Inf4GMyj3iOvRBrUPWTdzy03aACPI8ZUPo8g3IYvYdmseoYDCw7DGcoiF5xdlGKuI9+grOUYHQtvendIRDhzdFmGRPsT5e8vwPVB3FY68Xhn1TrkwV6o6MKH4pp+BEp1VzUXgrDsGQiZbyc36UCAwEAAaOBtTCBsjAOBgNVHQ8BAf8EBAMCBaAwCQYDVR0TBAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwNgYDVR0RBC8wLYIrdnN0cy12c3RzZ2hydC1naC12c28tb2F1dGgudmlzdWFsc3R1ZGlvLmNvbTAfBgNVHSMEGDAWgBRZBaZCR9ghvStfcWaGwuHGjrfTgzAdBgNVHQ4EFgQUWQWmQkfYIb0rX3FmhsLhxo6304MwDQYJKoZIhvcNAQELBQADggEBAGNdfALe6mdxQ67QL8GlW4dfFwvCX87JOeZThZ9uCj1+x1xUnywoR4o5q2DVI/JCvBRPn0BUb3dEVWLECXDHGjblesWZGMdSGYhMzWRQjVNmCYBC1ZM5QvonWCBcGkd72mZx0eFHnJCAP/TqEEpRvMHR+OOtSiZWV9zZpF1tf06AjKwT64F9V8PCmSIqPJXcTQXKKfkHZmGUk9AYF875+/FfzF89tCnT53UEh5BldFz0SAls+NhexbW/oOokBNCVqe+T2xXizktbFnFAFaomvwjVSvIeu3i/0Ygywl+3s5izMEsZ1T1ydIytv4FZf2JCHgRpmGPWJ5A7TpxuHSiE8Do="],"x5t":"eBZ_cn3sXYAd0ch4THBKHIgOwOE"},{"n":"wgCsNL8S6evSH_AHBsps2ccIHSwLpuEUGS9GYenGmGkSKyWefKsZheKl_84voiUgduuKcKA2aWQezp9338LjtlBmTHjopzAeU-Q3_IvqNf7BfrEAzEyp-ymdhNzPTE7Snmr5o_9AeiP1ZDBo35FaULgVUECJ3AzAM36zkURax3VNZRRZx1gb8lPUs9M5Yw6aZpHSOd6q_QzE8CP1OhGrAdoBzZ6ZCElon0kI-IuRLCwKptS7Yroi5-RtEKD2W458axNAQ36Yw93N8kInUC1QZDPrKd4QfYiG68ywjBoxp_bjNg5kh4LJmq1mwyGdNQV6F1Ew_jYlmou2Y8wvHQRJPQ","kty":"RSA","kid":"52F197C481DE70112C441B4A9B37B53C7FCF0DB5","alg":"RS256","e":"AQAB","use":"sig","x5c":["MIIDrDCCApSgAwIBAgIQLQnoXJ3HT6uPYvEofvOZ6zANBgkqhkiG9w0BAQsFADA2MTQwMgYDVQQDEyt2c3RzLXZzdHNnaHJ0LWdoLXZzby1vYXV0aC52aXN1YWxzdHVkaW8uY29tMB4XDTIxMTIwNjE5MDUyMloXDTIzMTIwNjE5MTUyMlowNjE0MDIGA1UEAxMrdnN0cy12c3RzZ2hydC1naC12c28tb2F1dGgudmlzdWFsc3R1ZGlvLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIArDS/Eunr0h/wBwbKbNnHCB0sC6bhFBkvRmHpxphpEislnnyrGYXipf/OL6IlIHbrinCgNmlkHs6fd9/C47ZQZkx46KcwHlPkN/yL6jX+wX6xAMxMqfspnYTcz0xO0p5q+aP/QHoj9WQwaN+RWlC4FVBAidwMwDN+s5FEWsd1TWUUWcdYG/JT1LPTOWMOmmaR0jneqv0MxPAj9ToRqwHaAc2emQhJaJ9JCPiLkSwsCqbUu2K6IufkbRCg9luOfGsTQEN+mMPdzfJCJ1AtUGQz6yneEH2IhuvMsIwaMaf24zYOZIeCyZqtZsMhnTUFehdRMP42JZqLtmPMLx0EST0CAwEAAaOBtTCBsjAOBgNVHQ8BAf8EBAMCBaAwCQYDVR0TBAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwNgYDVR0RBC8wLYIrdnN0cy12c3RzZ2hydC1naC12c28tb2F1dGgudmlzdWFsc3R1ZGlvLmNvbTAfBgNVHSMEGDAWgBTTNQQWmG4PZZsdfMeamCH1YcyDZTAdBgNVHQ4EFgQU0zUEFphuD2WbHXzHmpgh9WHMg2UwDQYJKoZIhvcNAQELBQADggEBAK/d+HzBSRac7p6CTEolRXcBrBmmeJUDbBy20/XA6/lmKq73dgc/za5VA6Kpfd6EFmG119tl2rVGBMkQwRx8Ksr62JxmCw3DaEhE8ZjRARhzgSiljqXHlk8TbNnKswHxWmi4MD2/8QhHJwFj3X35RrdMM4R0dN/ojLlWsY9jXMOAvcSBQPBqttn/BjNzvn93GDrVafyX9CPl8wH40MuWS/gZtXeYIQg5geQkHCyP96M5Sy8ZABOo9MSIfPRw1F7dqzVuvliul9ZZGV2LsxmZCBtbsCkBau0amerigZjud8e9SNp0gaJ6wGhLbstCZIdaAzS5mSHVDceQzLrX2oe1h4k="],"x5t":"UvGXxIHecBEsRBtKmze1PH_PDbU"}]}`))
108+
109+
queryStringParams := make(map[string]string)
110+
queryStringParams["owner"] = "varunsh-coder"
111+
queryStringParams["repo"] = "actions-playground"
112+
queryStringParams["runid"] = "2800694956"
113+
mockDynamoDbSvc := &mockDynamoDBClient{}
114+
115+
tests := []struct {
116+
name string
117+
args args
118+
want *GitHubWorkflowSecrets
119+
wantErr bool
120+
}{
121+
{name: "call from user", args: args{queryStringParams: queryStringParams, authHeader: "", svc: mockDynamoDbSvc},
122+
want: &GitHubWorkflowSecrets{Repo: "varunsh-coder/actions-playground", RunId: "2800694956", AreSecretsSet: true, Secrets: []Secret{{Name: "test"}}}, wantErr: false},
123+
{name: "call from action", args: args{queryStringParams: queryStringParams, authHeader: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImVCWl9jbjNzWFlBZDBjaDRUSEJLSElnT3dPRSIsImtpZCI6Ijc4MTY3RjcyN0RFQzVEODAxREQxQzg3ODRDNzA0QTFDODgwRUMwRTEifQ.eyJqdGkiOiIzNGI0YTM1Ny05MjQ1LTRmYjgtOTlmYy00NDc3OWRiM2NmMzkiLCJzdWIiOiJyZXBvOnZhcnVuc2gtY29kZXIvYWN0aW9ucy1wbGF5Z3JvdW5kOnJlZjpyZWZzL2hlYWRzL21haW4iLCJhdWQiOiJodHRwczovL2dpdGh1Yi5jb20vdmFydW5zaC1jb2RlciIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6IjUzNmNmN2IwNGVlZGEyYmQ2ZGFmOTBjNTgzM2Q5ZTkwYjk1MTkyNGUiLCJyZXBvc2l0b3J5IjoidmFydW5zaC1jb2Rlci9hY3Rpb25zLXBsYXlncm91bmQiLCJyZXBvc2l0b3J5X293bmVyIjoidmFydW5zaC1jb2RlciIsInJlcG9zaXRvcnlfb3duZXJfaWQiOiIyNTAxNTkxNyIsInJ1bl9pZCI6IjI4MDA2OTQ5NTYiLCJydW5fbnVtYmVyIjoiNiIsInJ1bl9hdHRlbXB0IjoiMSIsInJlcG9zaXRvcnlfdmlzaWJpbGl0eSI6InB1YmxpYyIsInJlcG9zaXRvcnlfaWQiOiI0MzM5MDM3OTIiLCJhY3Rvcl9pZCI6IjI1MDE1OTE3IiwiYWN0b3IiOiJ2YXJ1bnNoLWNvZGVyIiwid29ya2Zsb3ciOiJQdWJsaXNoIFBhY2thZ2UgdG8gbnBtanMiLCJoZWFkX3JlZiI6IiIsImJhc2VfcmVmIjoiIiwiZXZlbnRfbmFtZSI6IndvcmtmbG93X2Rpc3BhdGNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJqb2Jfd29ya2Zsb3dfcmVmIjoidmFydW5zaC1jb2Rlci9hY3Rpb25zLXBsYXlncm91bmQvLmdpdGh1Yi93b3JrZmxvd3MvbWZhX3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsImlzcyI6Imh0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20iLCJuYmYiOjE2NTk2NjIzOTMsImV4cCI6MTY1OTY2MzI5MywiaWF0IjoxNjU5NjYyOTkzfQ.O-SRv44w8cHSsvQ40ntM5yqXTx4xLnp3koHZVwNcnes2DPGzbcXbf_qzmJqwpSVBqBjQUDS-nKLD_NgM8XSSgIQiTTIL0CBgZCb2FAwkYaVFWoMR38F1Z2OvHKz_WgsvaTX9thfMHyTe3gbFr1B8JSv2MeBQbFODCw7F1mkIPGPCd5wVAKjY3ECZp2JCmQ8nNvMtZj-HvuK5g3bXRpZASePufjhN2MP2y_ewGydWyNYIT6_sNIw8pab4eeD7VEaCTaxq4_yQkayPr49_xB5-g8H6LvY_aLMczJq9NpQMboEfFtlnQVQ90g4F7bFQd_cdMZPquKT0AJmDEsu04F1Hag", svc: mockDynamoDbSvc},
124+
want: &GitHubWorkflowSecrets{Repo: "varunsh-coder/actions-playground", RunId: "2800694956", AreSecretsSet: true, Secrets: []Secret{{Name: "test", Value: "123"}}}, wantErr: false},
125+
}
126+
for _, tt := range tests {
127+
t.Run(tt.name, func(t *testing.T) {
128+
got, err := GetSecrets(tt.args.queryStringParams, tt.args.authHeader, tt.args.svc, true)
129+
if (err != nil) != tt.wantErr {
130+
t.Errorf("GetSecrets() error = %v, wantErr %v", err, tt.wantErr)
131+
return
132+
}
133+
if !reflect.DeepEqual(got, tt.want) {
134+
t.Errorf("GetSecrets() = %v, want %v", got, tt.want)
135+
}
136+
})
137+
}
138+
}

0 commit comments

Comments
 (0)