Skip to content

Conversation

@danielbotros
Copy link
Member

@danielbotros danielbotros commented Dec 29, 2025

Description

APP-14487 Update viam-agent to parse and authenticate with API keys

  • Similar to RDK side of changes found here
  • Changes related to the Cloud part of the config in order to parse and validate API keys in order to use them as the primary auth credentials moving forward, using secrets as a fallback.
  • Changes related to propagating API keys to anywhere we need to authenticate (i.e. Net appender) or reading/writing config/creds.

Testing

Config used / manually modified:

{"cloud":{"app_address":"https://app.viam.com:443","id":"<id-value>","secret":"<secret-value>", "api_key":{"id":"<api-key-id>","value":"<api-key-value>"}}}
  • I tested connecting a agent managed robot to prod app using both a robot part secret, an API key, and both.

@danielbotros danielbotros force-pushed the APP-14487-update-agent-to-priortize-api-key-creds branch from 97a9c95 to b8f6c18 Compare December 31, 2025 17:58
Comment on lines +295 to +298

replace go.viam.com/rdk => ../rdk

replace github.com/nunnatsa/ginkgolinter => github.com/nunnatsa/ginkgolinter v0.16.2
Copy link
Member Author

@danielbotros danielbotros Dec 31, 2025

Choose a reason for hiding this comment

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

Need to wait for RDK release with other changes to upgrade RDK version and to test on a PI before merging, but hoping to get some eyes on beforehand.

I'm running in various linter dependency issues with upgrading the RDK. I need to add replace github.com/nunnatsa/ginkgolinter => github.com/nunnatsa/ginkgolinter v0.16.2 to go.mod otherwise I get these errors:

go: finding module for package github.com/nunnatsa/ginkgolinter/types
go: github.com/golangci/golangci-lint/cmd/golangci-lint imports
        github.com/golangci/golangci-lint/pkg/commands imports
        github.com/golangci/golangci-lint/pkg/lint/lintersdb imports
        github.com/golangci/golangci-lint/pkg/golinters/ginkgolinter imports
        github.com/nunnatsa/ginkgolinter/types: module github.com/nunnatsa/ginkgolinter@latest found (v0.21.2), but does not contain package github.com/nunnatsa/ginkgolinter/types

yet I still cannot lint because of this error:

../../go/pkg/mod/github.com/golangci/golangci-lint@v1.64.5/pkg/golinters/dupl/dupl.go:8:2: import "github.com/golangci/dupl" is a program, not an importable package

@danielbotros danielbotros changed the title Update agent to use API keys when they exist [APP-14487] Update viam-agent to parse and authenticate with API keys Dec 31, 2025
@danielbotros danielbotros marked this pull request as ready for review December 31, 2025 18:44
Comment on lines 12 to 15
type APIKey struct {
ID string `json:"id"`
Value string `json:"value"`
}
Copy link
Member

Choose a reason for hiding this comment

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

Should this say "key" instead of "value" to be consistent with https://github.com/viamrobotics/app/pull/10703?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah good catch thank you!

return
}
if cfg.Cloud == nil || (cfg.Cloud.ID == "" || cfg.Cloud.Secret == "" || cfg.Cloud.AppAddress == "") {
if cfg.Cloud == nil || (cfg.Cloud.ID == "" || (cfg.Cloud.Secret == "" || cfg.Cloud.APIKey.IsEmpty()) || cfg.Cloud.AppAddress == "") {
Copy link
Member

@edobranov edobranov Dec 31, 2025

Choose a reason for hiding this comment

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

Not sure what this function does and I see that we still have n.portalData.input.Secret = cloud.GetSecret() in the other file, but do we indeed want to require that both a secret and API key is present here?

Mostly wondering about the intention since it goes against how you tested connecting and we're using && in parseOpts.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't have a strong opinion of requiring both, but the intention was just to check that at least one of API key or secret exists in the cloud config so if secrets ever get removed this code doesn't need to be updated.

The logic in parseOpts is a bit hard to read so I might try to refactor it but that is enforcing that if one cloud config field is present then we must have a fully valid cloud config (that is, at least of API key or secret exists), but an empty cloud config is also ok. Whereas these checks enforce that we always have a complete cloud config (empty not ok), completing meaning at least one of API key or secret.

Copy link
Member

Choose a reason for hiding this comment

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

completing meaning at least one of API key or secret.

Right, I think right now we're returning an error if one is missing here. It'd have to be && for us to allow one to be missing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops yeah you are right. I was thinking these if-statements were the allowable conditions not the error condition.

}

if cfg.Cloud.AppAddress == "" || cfg.Cloud.ID == "" || cfg.Cloud.Secret == "" {
if cfg.Cloud.AppAddress == "" || cfg.Cloud.ID == "" || (cfg.Cloud.Secret == "" || cfg.Cloud.APIKey.IsEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

(same as my other question, probably gonna be the same answer)

AppAddr string `default:"https://app.viam.com:443" description:"Cloud address to set in viam.json" long:"app-addr"`
PartID string `description:"PartID to set in viam.json" long:"part-id"`
Secret string `description:"Device secret to set in viam.json" long:"secret"`
APIKey utils.APIKey `description:"Device secret to set in viam.json" long:"api-key"`
Copy link
Member

Choose a reason for hiding this comment

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

did you test the bt provisioning flow and how did you do it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants