Skip to content
Merged
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
41 changes: 26 additions & 15 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
version: "2"
run:
# Our CI expects a vendor directory, hence we have to use -mod=readonly here as well.
modules-download-mode: readonly
deadline: 30m
timeout: 5m

# default linters are enabled `golangci-lint help linters`
linters:
disable-all: true
default: none
enable:
- errcheck
- gosec
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- stylecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It seems we are removing stylecheck. Is v2 not supporting this or any other reason?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yep, stylecheck has been merged into staticcheck 🙂 (also a few others) source: https://golangci-lint.run/docs/product/migration-guide/#lintersenablestylecheckgosimplestaticcheck

- errcheck
- gosec
- govet
- ineffassign
- staticcheck
- unused
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
formatters:
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
5 changes: 1 addition & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,10 @@ make lint-in-container
The project uses golangci-lint with the following enabled linters:
- errcheck
- gosec
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- stylecheck

## Development Workflow

Expand All @@ -105,4 +102,4 @@ The project uses golangci-lint with the following enabled linters:
- This is an OCM plugin - the binary has prefix `ocm-` and can be invoked as `ocm backplane`
- Configuration file expected at `$HOME/.config/backplane/config.json`
- The project uses Go modules with vendoring
- Static linking is used for the final binary
- Static linking is used for the final binary
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ GO_BUILD_FLAGS :=-tags 'include_gcs include_oss containers_image_openpgp gssapi'
GO_BUILD_FLAGS_DARWIN :=-tags 'include_gcs include_oss containers_image_openpgp'
GO_BUILD_FLAGS_LINUX_CROSS :=-tags 'include_gcs include_oss containers_image_openpgp'

GOLANGCI_LINT_VERSION=v1.61.0
GOLANGCI_LINT_VERSION=v2.5.0
GORELEASER_VERSION=v1.14.1
GOVULNCHECK_VERSION=v1.0.1

Expand Down Expand Up @@ -66,8 +66,8 @@ test-in-container: build-image
# Installed using instructions from: https://golangci-lint.run/usage/install/#linux-and-windows
getlint:
@mkdir -p $(GOPATH)/bin
@ls $(GOPATH)/bin/golangci-lint 1>/dev/null || (echo "Installing golangci-lint..." && curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you elaborate on why we are removing the ls check here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The main reason for the change here is to ensure golangci-lint is reinstalled properly each time, I think ls itself wouldn't be an issue but our CI did keep failing until I forced it to overwrite the existing installation to ensure the latest version is installed.


@echo "Installing golangci-lint $(GOLANGCI_LINT_VERSION)..."
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION)
.PHONY: lint
lint: getlint
$(GOPATH)/bin/golangci-lint run --timeout 5m
Expand Down Expand Up @@ -128,7 +128,7 @@ mock-gen:

.PHONY: build-image
build-image:
$(CONTAINER_ENGINE) build --pull --platform linux/amd64 --build-arg=GOLANGCI_LINT_VERSION -t backplane-cli-builder -f ./make.Dockerfile .
$(CONTAINER_ENGINE) build --pull --platform linux/amd64 --build-arg GOLANGCI_LINT_VERSION=$(GOLANGCI_LINT_VERSION) -t backplane-cli-builder -f ./make.Dockerfile .

.PHONY: lint-in-container
lint-in-container: build-image
Expand Down
32 changes: 16 additions & 16 deletions cmd/ocm-backplane/cloud/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (cfg *QueryConfig) GetCloudConsole() (*ConsoleResponse, error) {
func (cfg *QueryConfig) getCloudConsoleFromPublicAPI(ocmToken string) (*ConsoleResponse, error) {
logger.Debugln("Getting Cloud Console")

client, err := backplaneapi.DefaultClientUtils.GetBackplaneClient(cfg.BackplaneConfiguration.URL, ocmToken, cfg.BackplaneConfiguration.ProxyURL)
client, err := backplaneapi.DefaultClientUtils.GetBackplaneClient(cfg.URL, ocmToken, cfg.ProxyURL)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -173,7 +173,7 @@ func (cfg *QueryConfig) GetCloudCredentials() (bpCredentials.Response, error) {
}

func (cfg *QueryConfig) getCloudCredentialsFromBackplaneAPI(ocmToken string) (bpCredentials.Response, error) {
client, err := backplaneapi.DefaultClientUtils.GetBackplaneClient(cfg.BackplaneConfiguration.URL, ocmToken, cfg.BackplaneConfiguration.ProxyURL)
client, err := backplaneapi.DefaultClientUtils.GetBackplaneClient(cfg.URL, ocmToken, cfg.ProxyURL)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -243,15 +243,15 @@ func (cfg *QueryConfig) getIsolatedCredentials(ocmToken string) (aws.Credentials
return aws.Credentials{}, fmt.Errorf("unable to extract email from given token: %w", err)
}

if cfg.BackplaneConfiguration.AssumeInitialArn == "" {
if cfg.AssumeInitialArn == "" {
// If not provided as an override, attempt to automatically set this based on OCM url
switch cfg.OcmConnection.URL() {
case productionOCMUrl:
cfg.BackplaneConfiguration.AssumeInitialArn = productionAssumeInitialArn
cfg.AssumeInitialArn = productionAssumeInitialArn
case stagingOCMUrl:
cfg.BackplaneConfiguration.AssumeInitialArn = stagingAssumeInitialArn
cfg.AssumeInitialArn = stagingAssumeInitialArn
case integrationOCMUrl:
cfg.BackplaneConfiguration.AssumeInitialArn = integrationAssumeInitialArn
cfg.AssumeInitialArn = integrationAssumeInitialArn
default:
logger.Infof("failed to automatically set assume-initial-arn based on OCM url: %s", cfg.OcmConnection.URL())
return aws.Credentials{}, errors.New("backplane config is missing required `assume-initial-arn` property")
Expand All @@ -263,11 +263,11 @@ func (cfg *QueryConfig) getIsolatedCredentials(ocmToken string) (aws.Credentials
stagingAssumeInitialArn,
integrationAssumeInitialArn,
},
cfg.BackplaneConfiguration.AssumeInitialArn,
cfg.AssumeInitialArn,
) {
logger.Warnf("assume-initial-arn in backplane config is not set to a valid payer ARN, using: %s", cfg.BackplaneConfiguration.AssumeInitialArn)
logger.Warnf("assume-initial-arn in backplane config is not set to a valid payer ARN, using: %s", cfg.AssumeInitialArn)
return aws.Credentials{}, fmt.Errorf("invalid assume-initial-arn: %s, must be one of: prod: %s, stage: %s, int: %s",
cfg.BackplaneConfiguration.AssumeInitialArn,
cfg.AssumeInitialArn,
productionAssumeInitialArn,
stagingAssumeInitialArn,
integrationAssumeInitialArn,
Expand All @@ -276,19 +276,19 @@ func (cfg *QueryConfig) getIsolatedCredentials(ocmToken string) (aws.Credentials
}
// Use AWS-specific proxy for initial STS client, fallback to regular proxy
// Priority: 1) AWS proxy from config; 2) regular proxy from local backplane config
stsProxyURL := cfg.BackplaneConfiguration.GetAwsProxy()
stsProxyURL := cfg.GetAwsProxy()
initialClient, err := StsClient(stsProxyURL)
if err != nil {
return aws.Credentials{}, fmt.Errorf("failed to create sts client: %w", err)
}

seedCredentials, err := AssumeRoleWithJWT(ocmToken, cfg.BackplaneConfiguration.AssumeInitialArn, initialClient)
seedCredentials, err := AssumeRoleWithJWT(ocmToken, cfg.AssumeInitialArn, initialClient)
if err != nil {
return aws.Credentials{}, fmt.Errorf("failed to assume role using JWT: %w", err)
}
// Verify Sts connection with the seed credentials
// Use AWS-specific proxy for STS operations
awsProxyURL := cfg.BackplaneConfiguration.GetAwsProxy()
awsProxyURL := cfg.GetAwsProxy()

var stsClientConfig aws.Config
if awsProxyURL != nil {
Expand Down Expand Up @@ -317,7 +317,7 @@ func (cfg *QueryConfig) getIsolatedCredentials(ocmToken string) (aws.Credentials
return aws.Credentials{}, fmt.Errorf("unable to connect to AWS STS endpoint (GetCallerIdentity failed): %w", err)
}

backplaneClient, err := backplaneapi.DefaultClientUtils.GetBackplaneClient(cfg.BackplaneConfiguration.URL, ocmToken, cfg.BackplaneConfiguration.ProxyURL)
backplaneClient, err := backplaneapi.DefaultClientUtils.GetBackplaneClient(cfg.URL, ocmToken, cfg.ProxyURL)
if err != nil {
return aws.Credentials{}, fmt.Errorf("failed to create backplane client with access token: %w", err)
}
Expand Down Expand Up @@ -386,7 +386,7 @@ func (cfg *QueryConfig) getIsolatedCredentials(ocmToken string) (aws.Credentials

// Use AWS-specific proxy for role sequence, fallback to regular proxy
// Priority: 1) AWS proxy from config, 2) regular proxy from config
roleSequenceProxyURL := cfg.BackplaneConfiguration.GetAwsProxy()
roleSequenceProxyURL := cfg.GetAwsProxy()
targetCredentials, err := AssumeRoleSequence(
seedClient,
assumeRoleArnSessionSequence,
Expand All @@ -405,7 +405,7 @@ func verifyTrustedIPAndGetPolicy(cfg *QueryConfig) (awsutil.PolicyDocument, erro
// Use AWS-specific proxy for egress IP check, fallback to regular proxy
// Priority: 1) AWS proxy from config, 2) regular proxy from config
var egressProxyURL *url.URL
if proxyURLString := cfg.BackplaneConfiguration.GetAwsProxy(); proxyURLString != nil {
if proxyURLString := cfg.GetAwsProxy(); proxyURLString != nil {
var err error
egressProxyURL, err = url.Parse(*proxyURLString)
if err != nil {
Expand Down Expand Up @@ -453,7 +453,7 @@ func checkEgressIPImpl(client *http.Client, url string) (net.IP, error) {
if err != nil {
return nil, fmt.Errorf("failed to fetch IP: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

body, err := io.ReadAll(resp.Body)
if err != nil {
Expand Down
30 changes: 15 additions & 15 deletions cmd/ocm-backplane/cloud/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ var _ = Describe("getIsolatedCredentials", func() {
Expect(err).To(Equal(fmt.Errorf("must provide non-empty cluster ID")))
})
It("should fail if wrong assume initial ARN is provided", func() {
testQueryConfig.BackplaneConfiguration.AssumeInitialArn = "arn:aws:iam::10000000:role/TEST_USER"
testQueryConfig.AssumeInitialArn = "arn:aws:iam::10000000:role/TEST_USER"
_, err := testQueryConfig.getIsolatedCredentials(testOcmToken)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("invalid assume-initial-arn: arn:aws:iam::10000000:role/TEST_USER, must be one of:"))
Expand Down Expand Up @@ -299,7 +299,7 @@ var _ = Describe("getIsolatedCredentials", func() {
})
It("should return an error when response body is not a valid IP", func() {
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "not-an-ip")
_, _ = fmt.Fprint(w, "not-an-ip")
}))
client = server.Client()

Expand Down Expand Up @@ -453,7 +453,7 @@ var _ = Describe("getIsolatedCredentials", func() {
It("should successfully verify IP and return policy when IP is in trusted range", func() {
// Mock the IP check to return a valid IP
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "209.10.10.10") // IP that matches our test trusted range
_, _ = fmt.Fprint(w, "209.10.10.10") // IP that matches our test trusted range
}))
defer server.Close()

Expand Down Expand Up @@ -484,7 +484,7 @@ var _ = Describe("getIsolatedCredentials", func() {
It("should fail when client IP is not in trusted range", func() {
// Mock the IP check to return an untrusted IP
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "192.168.1.1") // IP that doesn't match our test trusted range
_, _ = fmt.Fprint(w, "192.168.1.1") // IP that doesn't match our test trusted range
}))
defer server.Close()

Expand Down Expand Up @@ -513,7 +513,7 @@ var _ = Describe("getIsolatedCredentials", func() {

It("should fail when AWS proxy URL is invalid", func() {
// Set an invalid AWS proxy URL in configuration
testQueryConfig.BackplaneConfiguration.AwsProxy = aws.String("://invalid-url")
testQueryConfig.AwsProxy = aws.String("://invalid-url")

// Call the function
_, err := verifyTrustedIPAndGetPolicy(&testQueryConfig)
Expand All @@ -526,7 +526,7 @@ var _ = Describe("getIsolatedCredentials", func() {
Context("Execute getIsolatedCredentials with AwsProxy", func() {
It("should use AwsProxy configuration for AWS STS calls", func() {
// Set AWS proxy in configuration
testQueryConfig.BackplaneConfiguration.AwsProxy = aws.String("http://aws-proxy:8080")
testQueryConfig.AwsProxy = aws.String("http://aws-proxy:8080")

// Mock CheckEgressIP to avoid real HTTP calls
originalCheckEgressIP := CheckEgressIP
Expand Down Expand Up @@ -595,8 +595,8 @@ var _ = Describe("getIsolatedCredentials", func() {

It("should use AWS proxy when both ProxyURL and AwsProxy are configured", func() {
// Set both explicit proxy and AWS proxy in configuration
testQueryConfig.BackplaneConfiguration.ProxyURL = aws.String("http://regular-proxy:9090")
testQueryConfig.BackplaneConfiguration.AwsProxy = aws.String("http://aws-proxy:8080")
testQueryConfig.ProxyURL = aws.String("http://regular-proxy:9090")
testQueryConfig.AwsProxy = aws.String("http://aws-proxy:8080")

// Mock CheckEgressIP to avoid real HTTP calls
originalCheckEgressIP := CheckEgressIP
Expand Down Expand Up @@ -662,8 +662,8 @@ var _ = Describe("getIsolatedCredentials", func() {

It("should use regular proxy when AwsProxy is not configured", func() {
// Ensure AwsProxy is not set (should be nil by default)
testQueryConfig.BackplaneConfiguration.AwsProxy = nil
testQueryConfig.BackplaneConfiguration.ProxyURL = aws.String("http://regular-proxy:8080")
testQueryConfig.AwsProxy = nil
testQueryConfig.ProxyURL = aws.String("http://regular-proxy:8080")

// Mock CheckEgressIP to avoid real HTTP calls
originalCheckEgressIP := CheckEgressIP
Expand Down Expand Up @@ -732,8 +732,8 @@ var _ = Describe("getIsolatedCredentials", func() {
Context("Proxy separation verification", func() {
It("should demonstrate traffic separation between AWS and Backplane API calls", func() {
// Set different proxies for AWS and Backplane
testQueryConfig.BackplaneConfiguration.ProxyURL = aws.String("http://backplane-proxy:8080")
testQueryConfig.BackplaneConfiguration.AwsProxy = aws.String("http://aws-proxy:8080")
testQueryConfig.ProxyURL = aws.String("http://backplane-proxy:8080")
testQueryConfig.AwsProxy = aws.String("http://aws-proxy:8080")

// Mock CheckEgressIP to avoid real HTTP calls
originalCheckEgressIP := CheckEgressIP
Expand Down Expand Up @@ -814,7 +814,7 @@ var _ = Describe("getIsolatedCredentials", func() {

It("should handle proxy separation in verifyTrustedIPAndGetPolicy", func() {
// Set AWS-specific proxy in configuration
testQueryConfig.BackplaneConfiguration.AwsProxy = aws.String("http://aws-proxy:8080")
testQueryConfig.AwsProxy = aws.String("http://aws-proxy:8080")

// Mock checkEgressIP to avoid real HTTP calls
originalCheckEgressIP := CheckEgressIP
Expand All @@ -840,10 +840,10 @@ var _ = Describe("getIsolatedCredentials", func() {

It("should fallback to regular proxy when AwsProxy is not configured (regression test)", func() {
// Ensure AwsProxy is not set (should be nil by default)
testQueryConfig.BackplaneConfiguration.AwsProxy = nil
testQueryConfig.AwsProxy = nil

// Should fall back to regular proxy behavior
testQueryConfig.BackplaneConfiguration.ProxyURL = aws.String("http://regular-proxy:8080")
testQueryConfig.ProxyURL = aws.String("http://regular-proxy:8080")

// Mock CheckEgressIP to avoid real HTTP calls
originalCheckEgressIP := CheckEgressIP
Expand Down
4 changes: 2 additions & 2 deletions cmd/ocm-backplane/cloud/console_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ var _ = Describe("Cloud console command", func() {

// Disabled log output
log.SetOutput(io.Discard)
os.Setenv(info.BackplaneURLEnvName, proxyURI)
_ = os.Setenv(info.BackplaneURLEnvName, proxyURI)
})

AfterEach(func() {
os.Setenv(info.BackplaneURLEnvName, "")
_ = os.Setenv(info.BackplaneURLEnvName, "")
mockCtrl.Finish()
})
})
4 changes: 2 additions & 2 deletions cmd/ocm-backplane/cloud/credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,11 @@ var _ = Describe("Cloud console command", func() {

// Disabled log output
log.SetOutput(io.Discard)
os.Setenv(info.BackplaneURLEnvName, proxyURI)
_ = os.Setenv(info.BackplaneURLEnvName, proxyURI)
})

AfterEach(func() {
os.Setenv(info.BackplaneURLEnvName, "")
_ = os.Setenv(info.BackplaneURLEnvName, "")
mockCtrl.Finish()
})

Expand Down
6 changes: 3 additions & 3 deletions cmd/ocm-backplane/cloud/ssm.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ func startSSMsession(cmd *cobra.Command, execCommand []string) error {
}

// Set AWS credentials in environment variables
os.Setenv("AWS_ACCESS_KEY_ID", creds.AccessKeyID)
os.Setenv("AWS_SECRET_ACCESS_KEY", creds.SecretAccessKey)
os.Setenv("AWS_SESSION_TOKEN", creds.SessionToken)
_ = os.Setenv("AWS_ACCESS_KEY_ID", creds.AccessKeyID)
_ = os.Setenv("AWS_SECRET_ACCESS_KEY", creds.SecretAccessKey)
_ = os.Setenv("AWS_SESSION_TOKEN", creds.SessionToken)

// Load AWS SDK configuration with the custom HTTP client
cfg, err := awsConfig.LoadDefaultConfig(
Expand Down
6 changes: 3 additions & 3 deletions cmd/ocm-backplane/cloud/ssm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ var _ = Describe("SSM command", func() {
AfterEach(func() {
ExecCommand = originalExecCommand
ssmArgs.node = ""
os.Unsetenv("AWS_ACCESS_KEY_ID")
os.Unsetenv("AWS_SECRET_ACCESS_KEY")
os.Unsetenv("AWS_SESSION_TOKEN")
_ = os.Unsetenv("AWS_ACCESS_KEY_ID")
_ = os.Unsetenv("AWS_SECRET_ACCESS_KEY")
_ = os.Unsetenv("AWS_SESSION_TOKEN")
})

Context("startSSMsession", func() {
Expand Down
4 changes: 2 additions & 2 deletions cmd/ocm-backplane/config/troubleshoot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var _ = Describe("troubleshoot command", func() {
Expect(err).To(BeNil())

// set backplane config env with temp config file
os.Setenv("BACKPLANE_CONFIG", f.Name())
_ = os.Setenv("BACKPLANE_CONFIG", f.Name())
}

BeforeEach(func() {
Expand Down Expand Up @@ -146,7 +146,7 @@ var _ = Describe("troubleshoot command", func() {
CurrentContext: "default/test123/anonymous",
}
It("should print error if anything wrong in oc config", func() {
os.Setenv("KUBECONFIG", "/fake/path")
_ = os.Setenv("KUBECONFIG", "/fake/path")
o := troubleshootOptions{}
err := o.checkOC()
Expect(err).To(BeNil())
Expand Down
Loading