Skip to content

Commit f681da3

Browse files
authored
chore: security updates (#21)
1 parent 1af0676 commit f681da3

14 files changed

Lines changed: 671 additions & 147 deletions

File tree

.github/workflows/e2e.yml

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ on:
2525
env:
2626
GO_VERSION: "1.26"
2727

28+
permissions: read-all
29+
2830
jobs:
2931
e2e-tests:
3032
name: E2E Tests
@@ -37,10 +39,10 @@ jobs:
3739

3840
steps:
3941
- name: Checkout code
40-
uses: actions/checkout@v4
42+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
4143

4244
- name: Set up Go
43-
uses: actions/setup-go@v4
45+
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
4446
with:
4547
go-version: ${{ matrix.go-version }}
4648
cache: true
@@ -72,7 +74,7 @@ jobs:
7274

7375
- name: Run E2E tests with Ginkgo
7476
run: |
75-
go run github.com/onsi/ginkgo/v2/ginkgo run -v --timeout=10m --poll-progress-after=1m ./e2e
77+
go run github.com/onsi/ginkgo/v2/ginkgo@v2.28.0 run -v --timeout=10m --poll-progress-after=1m ./e2e
7678
env:
7779
CGO_ENABLED: 1
7880
continue-on-error: false
@@ -90,14 +92,14 @@ jobs:
9092

9193
- name: Upload coverage reports
9294
if: always()
93-
uses: actions/upload-artifact@v4
95+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
9496
with:
9597
name: e2e-coverage-${{ matrix.os }}
9698
path: coverage-e2e.*
9799

98100
- name: Upload test results
99101
if: always()
100-
uses: actions/upload-artifact@v4
102+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
101103
with:
102104
name: e2e-test-results-${{ matrix.os }}
103105
path: |
@@ -119,30 +121,20 @@ jobs:
119121
runs-on: ubuntu-latest
120122
timeout-minutes: 30
121123

122-
services:
123-
docker:
124-
image: docker:latest
125-
options: >-
126-
--privileged
127-
--health-cmd="docker ps"
128-
--health-interval=10s
129-
--health-timeout=5s
130-
--health-retries=5
131-
132124
steps:
133125
- name: Checkout code
134-
uses: actions/checkout@v4
126+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
135127

136128
- name: Set up Go
137-
uses: actions/setup-go@v4
129+
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
138130
with:
139131
go-version: "1.26"
140132
cache: true
141133
cache-dependency-path: go.sum
142134

143135
- name: Run E2E tests with verbose output
144136
run: |
145-
go run github.com/onsi/ginkgo/v2/ginkgo run -v -r --timeout=10m --poll-progress-after=1m ./e2e
137+
go run github.com/onsi/ginkgo/v2/ginkgo@v2.28.0 run -v -r --timeout=10m --poll-progress-after=1m ./e2e
146138
env:
147139
CGO_ENABLED: 1
148140

.github/workflows/release.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,29 @@ on:
55
branches:
66
- main
77

8-
permissions:
9-
contents: write
8+
permissions: read-all
109

1110
jobs:
1211
release:
1312
runs-on: ubuntu-latest
13+
permissions:
14+
contents: write
1415
steps:
1516
- name: Checkout repository
16-
uses: actions/checkout@v4
17+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
1718
with:
1819
fetch-depth: 0
1920

2021
- name: Calculate next version
2122
id: version
22-
uses: charlesthomas/github-action-svu@v1.1.4+3.2.3
23+
uses: charlesthomas/github-action-svu@da0337f57ff7d77c58363c32e9f863bfb01c0098 # v1.1.4+3.2.3
2324
with:
2425
cmd: patch
2526
pushTag: true
2627

2728
- name: Create GitHub Release
2829
if: steps.version.outputs.changed == 'true'
29-
uses: softprops/action-gh-release@v2
30+
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
3031
with:
3132
tag_name: ${{ steps.version.outputs.next }}
3233
generate_release_notes: true

.github/workflows/scorecard.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ jobs:
3030

3131
steps:
3232
- name: Checkout code
33-
uses: actions/checkout@v4
33+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
3434
with:
3535
persist-credentials: false
3636

3737
- name: Run analysis
38-
uses: ossf/scorecard-action@v2.4.3
38+
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
3939
with:
4040
results_file: results.sarif
4141
results_format: sarif
@@ -44,14 +44,14 @@ jobs:
4444

4545
# Upload the results as artifacts (optional)
4646
- name: Upload artifact
47-
uses: actions/upload-artifact@v4
47+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
4848
with:
4949
name: SARIF file
5050
path: results.sarif
5151
retention-days: 5
5252

5353
# Upload the results to GitHub's code scanning dashboard
5454
- name: Upload to code-scanning
55-
uses: github/codeql-action/upload-sarif@v3
55+
uses: github/codeql-action/upload-sarif@dd903d2e4f5405488e5ef1422510ee31c8b32357 # v3
5656
with:
5757
sarif_file: results.sarif

SECURITY.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Security Policy
2+
3+
## Reporting a Vulnerability
4+
5+
Please report suspected security vulnerabilities privately by emailing security@flanksource.com.
6+
7+
Include as much detail as possible, including affected versions, reproduction steps, impact, and any suggested remediation. We will acknowledge receipt and coordinate disclosure and fixes as appropriate.
8+
9+
## Supported Versions
10+
11+
Security fixes are provided for the current `main` branch and the latest released version.

api/config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package api
22

33
import (
4-
"crypto/md5"
4+
"crypto/sha256"
55
"encoding/hex"
66
"fmt"
77
"net/url"
@@ -75,9 +75,9 @@ func PrintableSecret(secret string) string {
7575
if len(secret) == 0 {
7676
return "<nil>"
7777
} else if len(secret) > 30 {
78-
sum := md5.Sum([]byte(secret))
78+
sum := sha256.Sum256([]byte(secret))
7979
hash := hex.EncodeToString(sum[:])
80-
return fmt.Sprintf("md5(%s),length=%d", hash[0:8], len(secret))
80+
return fmt.Sprintf("sha256(%s),length=%d", hash[0:8], len(secret))
8181
} else if len(secret) > 16 {
8282
return fmt.Sprintf("%s****%s", secret[0:1], secret[len(secret)-2:])
8383
} else if len(secret) > 10 {

connection/awskms.go

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package connection
22

33
import (
4+
"context"
5+
"errors"
46
"fmt"
57

6-
"github.com/flanksource/commons-db/context"
8+
"github.com/aws/aws-sdk-go-v2/aws"
9+
"github.com/aws/aws-sdk-go-v2/service/kms"
10+
"github.com/aws/aws-sdk-go-v2/service/kms/types"
11+
"github.com/aws/smithy-go"
12+
commonsContext "github.com/flanksource/commons-db/context"
713
"github.com/flanksource/commons-db/models"
14+
"gocloud.dev/gcerrors"
815
"gocloud.dev/secrets"
9-
"gocloud.dev/secrets/awskms"
16+
"gocloud.dev/secrets/driver"
1017
)
1118

1219
type AWSKMS struct {
@@ -25,17 +32,75 @@ func (t *AWSKMS) FromModel(conn models.Connection) {
2532
t.KeyID = conn.Properties["keyID"]
2633
}
2734

28-
func (t *AWSKMS) SecretKeeper(ctx context.Context) (*secrets.Keeper, error) {
35+
func (t *AWSKMS) SecretKeeper(ctx commonsContext.Context) (*secrets.Keeper, error) {
2936
awsConfig, err := t.AWSConnection.Client(ctx)
3037
if err != nil {
3138
return nil, fmt.Errorf("failed to create AWS client: %w", err)
3239
}
3340

34-
kmsClient, err := awskms.DialV2(awsConfig)
41+
keeper := secrets.NewKeeper(&awsKMSKeeper{
42+
keyID: t.KeyID,
43+
client: kms.NewFromConfig(awsConfig),
44+
})
45+
return keeper, nil
46+
}
47+
48+
type awsKMSKeeper struct {
49+
keyID string
50+
client *kms.Client
51+
}
52+
53+
var _ driver.Keeper = (*awsKMSKeeper)(nil)
54+
55+
func (k *awsKMSKeeper) Decrypt(ctx context.Context, ciphertext []byte) ([]byte, error) {
56+
result, err := k.client.Decrypt(ctx, &kms.DecryptInput{
57+
CiphertextBlob: ciphertext,
58+
})
3559
if err != nil {
36-
return nil, fmt.Errorf("failed to create AWS KMS client: %w", err)
60+
return nil, err
3761
}
62+
return result.Plaintext, nil
63+
}
3864

39-
keeper := awskms.OpenKeeperV2(kmsClient, t.KeyID, nil)
40-
return keeper, nil
65+
func (k *awsKMSKeeper) Encrypt(ctx context.Context, plaintext []byte) ([]byte, error) {
66+
result, err := k.client.Encrypt(ctx, &kms.EncryptInput{
67+
KeyId: aws.String(k.keyID),
68+
Plaintext: plaintext,
69+
})
70+
if err != nil {
71+
return nil, err
72+
}
73+
return result.CiphertextBlob, nil
74+
}
75+
76+
func (k *awsKMSKeeper) Close() error { return nil }
77+
78+
func (k *awsKMSKeeper) ErrorAs(err error, i any) bool {
79+
return errors.As(err, i)
80+
}
81+
82+
func (k *awsKMSKeeper) ErrorCode(err error) gcerrors.ErrorCode {
83+
var apiErr smithy.APIError
84+
if !errors.As(err, &apiErr) {
85+
return gcerrors.Unknown
86+
}
87+
88+
switch apiErr.ErrorCode() {
89+
case (&types.NotFoundException{}).ErrorCode():
90+
return gcerrors.NotFound
91+
case (&types.InvalidCiphertextException{}).ErrorCode(), (&types.InvalidKeyUsageException{}).ErrorCode():
92+
return gcerrors.InvalidArgument
93+
case (&types.KMSInternalException{}).ErrorCode():
94+
return gcerrors.Internal
95+
case (&types.KMSInvalidStateException{}).ErrorCode():
96+
return gcerrors.FailedPrecondition
97+
case (&types.DisabledException{}).ErrorCode(), (&types.InvalidGrantTokenException{}).ErrorCode():
98+
return gcerrors.PermissionDenied
99+
case (&types.KeyUnavailableException{}).ErrorCode():
100+
return gcerrors.ResourceExhausted
101+
case (&types.DependencyTimeoutException{}).ErrorCode():
102+
return gcerrors.DeadlineExceeded
103+
default:
104+
return gcerrors.Unknown
105+
}
41106
}

0 commit comments

Comments
 (0)