{"record":{"id":"471c8ef5194eb75c","repo":"netbirdio/netbird","slug":"generate-artifact-key-w","errorCode":null,"errorMessage":"generate artifact key: %w","messagePattern":"generate artifact key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/artifactkey.go","lineNumber":112,"sourceCode":"\t}\n}\n\nfunc handleCreateArtifactKey(cmd *cobra.Command, rootPrivKeyFile, artifactPrivKeyFile, artifactPubKeyFile string, expiration time.Duration) error {\n\tcmd.Println(\"Creating new artifact signing key...\")\n\n\tprivKeyPEM, err := os.ReadFile(rootPrivKeyFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read root private key file: %w\", err)\n\t}\n\n\tprivateRootKey, err := reposign.ParseRootKey(privKeyPEM)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse private root key: %w\", err)\n\t}\n\n\tartifactKey, privPEM, pubPEM, signature, err := reposign.GenerateArtifactKey(privateRootKey, expiration)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"generate artifact key: %w\", err)\n\t}\n\n\tif err := os.WriteFile(artifactPrivKeyFile, privPEM, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"write private key file (%s): %w\", artifactPrivKeyFile, err)\n\t}\n\n\tif err := os.WriteFile(artifactPubKeyFile, pubPEM, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"write public key file (%s): %w\", artifactPubKeyFile, err)\n\t}\n\n\tsignatureFile := artifactPubKeyFile + \".sig\"\n\tif err := os.WriteFile(signatureFile, signature, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"write signature file (%s): %w\", signatureFile, err)\n\t}\n\n\tcmd.Printf(\"✅ Artifact key created successfully.\\n\")\n\tcmd.Printf(\"%s\\n\", artifactKey.String())\n\treturn nil","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/artifactkey.go#L94-L130","documentation":"reposign.GenerateArtifactKey failed while creating a new artifact signing key signed by the root key. Its concrete failures are: the root key has expired (checked against rootKey.Metadata.ExpiresAt), ed25519 key generation errors (rare), PEM marshalling of the new key, or signing the key metadata with the root key.","triggerScenarios":"Invoking create-artifact-key with a root key whose ExpiresAt is in the past; a corrupted root key whose embedded metadata fails to serialize/sign. The overwhelming majority of real hits are the expired-root-key branch, which reports 'root key has expired on <RFC3339>'.","commonSituations":"Reusing a root key past its planned lifetime (default root keys are often created with bounded expiration); system clock skew making a valid root key look expired.","solutions":["Check the chained message; if it says 'root key has expired', generate a new root with create-root-key and re-sign artifact keys","Verify the system date/time (timedatectl or equivalent) if the key should still be valid","If it is a marshal/sign error, re-export or regenerate the root key, since the key material is likely corrupted"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before generating artifact keys, ensure the root key is still valid\nrootKey, err := reposign.ParseRootKey(privKeyPEM)\nif err != nil { ... }\nif time.Now().After(rootKey.Metadata.ExpiresAt) {\n    return fmt.Errorf(\"rotate root key first: expired on %s\", rootKey.Metadata.ExpiresAt.Format(time.RFC3339))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Alert on root key expiration well before the date (calendar/monitoring)","Create root keys with a lifetime longer than the planned artifact key rotation cycle","Keep NTP enabled on signing hosts to avoid clock-induced expiry"],"tags":["cli","cryptography","key-expiry","signing","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}