mirror of
https://github.com/zhaofengli/attic.git
synced 2025-03-05 16:27:06 +00:00
Make the nix flake check tests pass
This commit is contained in:
parent
9511afde4b
commit
d49cd3383b
7 changed files with 25 additions and 14 deletions
|
@ -14,13 +14,13 @@ Attic provides [a NixOS module](https://github.com/zhaofengli/attic/blob/main/ni
|
||||||
The RS256 JWT secret can be generated with the `openssl` utility:
|
The RS256 JWT secret can be generated with the `openssl` utility:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
openssl genrsa -traditional -out private_key.pem 4096
|
nix run nixpkgs#openssl -- genrsa -traditional -out - 4096 | base64 -w0
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a file on the server containing the following contents:
|
Create a file on the server containing the following contents:
|
||||||
|
|
||||||
```
|
```
|
||||||
ATTIC_SERVER_TOKEN_RS256_SECRET="output from openssl"
|
ATTIC_SERVER_TOKEN_RS256_SECRET="output from above"
|
||||||
```
|
```
|
||||||
|
|
||||||
Ensure the file is only accessible by root.
|
Ensure the file is only accessible by root.
|
||||||
|
|
|
@ -5,7 +5,7 @@ let
|
||||||
serverConfigFile = config.nodes.server.services.atticd.configFile;
|
serverConfigFile = config.nodes.server.services.atticd.configFile;
|
||||||
|
|
||||||
cmd = {
|
cmd = {
|
||||||
atticadm = "atticd-atticadm";
|
atticadm = ". /etc/atticd.env && export ATTIC_SERVER_TOKEN_RS256_SECRET && atticd-atticadm";
|
||||||
atticd = ". /etc/atticd.env && export ATTIC_SERVER_TOKEN_RS256_SECRET && atticd -f ${serverConfigFile}";
|
atticd = ". /etc/atticd.env && export ATTIC_SERVER_TOKEN_RS256_SECRET && atticd -f ${serverConfigFile}";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ in {
|
||||||
|
|
||||||
# For testing only - Don't actually do this
|
# For testing only - Don't actually do this
|
||||||
environment.etc."atticd.env".text = ''
|
environment.etc."atticd.env".text = ''
|
||||||
ATTIC_SERVER_TOKEN_RS256_SECRET="$(openssl genrsa -traditional -out - 512)"
|
ATTIC_SERVER_TOKEN_RS256_SECRET='LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBekhqUzFGKzlRaFFUdlJZYjZ0UGhxS09FME5VYkIraTJMOTByWVBNQVVoYVBUMmlKCmVUNk9vWFlmZWszZlZ1dXIrYks1VWFVRjhUbEx2Y1FHa1Arckd0WDRiQUpGTWJBcTF3Y25FQ3R6ZGVERHJnSlIKMGUvNWJhdXQwSS9YS0ticG9oYjNvWVhtUmR5eG9WVGE3akY1bk11ajBsd25kUTcwYTF1ZGkzMGNpYkdTWHZMagpVeGltL3ByYjUrV3ZPdjN4UnhlbDZHYmptUW1RMVBHeHVLcmx3b1ZKRnlWTjl3QmExajBDelJDcURnTFRwQWw0CjhLVWlDY2V1VUZQcmdZaW9vSVhyVExlWmxVbFVVV3FHSDBJbGFKeVUyQ05iNWJtZWM1TnZ4RDlaakFoYytucmgKRS80VzkxajdQMFVyQnp4am9NUTRlKzBPZDhmQnBvSDAwbm4xUXdJREFRQUJBb0lCQUE2RmxEK21Ed3gyM1pJRAoxSGJBbHBuQ0IwaEhvbFJVK0Q5OC96d3k5ZlplaU00VWVCTUcyTjFweE1HTWIweStqeWU4UkVJaXJNSGRsbDRECllvNEF3bmUwODZCRUp3TG81cG4vOVl2RjhqelFla1ZNLzkrZm9nRGlmUVUvZWdIMm5NZzR4bHlQNUhOWXdicmEKQ25SNVNoQlRQQzdRQWJOa0hRTFU3bUwrUHowZUlXaG9KWVRoUUpkU0g3RDB0K1QwZzVVNDdPam5qbXJaTWwxaApHOE1IUHhKMk5WU1l2N0dobnpjblZvcVVxYzlxeldXRDZXZERtV1BPNGJ1K2p0b2E2U2o4cjJtb0RRZ1A5YXNhCm93RUFJbHBmbVkxYUx2dENwWG4rejRTTWJKcHRXMlVvaktGa2dkYm9jZmtXYWdtSGZRa2xmS0dBQ0hibU9ZV24KeDRCbTU3a0NnWUVBN1dXaXJDZnBRR01hR3A2WWxMQlVUc1VJSXJOclF4UmtuRlc3dFVYd0NqWFZ5SDlTR3FqNgphTkNhYzZpaks3QVNBYXlxY1JQRjFPY2gyNmxpVmRKUHNuRGxwUjhEVXB2TzRVOVRzSTJyZ1lZYzNrSWkzVGFKClgzV0Vic1Z6Nk45WXFPSXlnVnZiTEhLS0F4Uyt4b1Z2SjkzQmdWRHN5SkxRdmhrM3VubXk3M2tDZ1lFQTNINnYKeUhOKzllOVAyOS9zMVY1eWZxSjdvdVdKV0lBTHFDYm9zOTRRSVdPSG5HRUtSSGkydWIzR0d6U2tRSzN1eTUrdQo4M0txaFJOejRVMkdOK1pLaFE0NHhNVmV4TUVvZzJVU3lTaVZ0cFdqWXBwT2Q1NnVaMzRWaFU2TWRNZS9zT0JnCnNoei84MUxUSis2cHdFZE9wV2tPVlRaMXJISlZXQmdtVk5qWjc1c0NnWUVBNVd5YjBaU2dyMEVYTVRLa2NzNFcKTENudXV0cDZodEZtaWsrd29IZCtpOStMUThFSU1BdXVOUzJrbHJJYlAxVmhrWXkxQzZMNFJkRTV2M2ZyT05XUApmL3ZyYzdDTkhZREdacWlyVUswWldvdXB5b0pQLzBsOWFXdkJHT3hxSUZ2NDZ2M3ZvV1NNWkdBdFVOenpvaGZDClhOeks3WmF2dndka0JOT0tNQVQ5RU1FQ2dZRUF3NEhaWDRWNUo1d2dWVGVDQ2RjSzhsb2tBbFpBcUNZeEw5SUEKTjZ4STVUSVpSb0dNMXhXcC81dlRrci9rZkMwOU5YUExiclZYbVZPY1JrTzFKTStmZDhjYWN1OEdqck11dHdMaAoyMWVQR0N3cWlQMkZZZTlqZVFTRkZJU0hhZXpMZll3V2NSZmhvdURudGRxYXpaRHNuU0kvd1RMZXVCOVFxU0lRCnF0NzByczBDZ1lCQ2lzV0VKdXpQUUlJNzVTVkU4UnJFZGtUeUdhOEVBOHltcStMdDVLRDhPYk80Q2JHYVFlWXkKWFpjSHVyOFg2cW1lWHZVU3MwMHBMMUdnTlJ3WCtSUjNMVDhXTm9vc0NqVDlEUW9GOFZveEtseDROVTRoUGlrTQpBc0w1RS9wYnVLeXkvSU5LTnQyT3ZPZmJYVitlTXZQdGs5c1dORjNyRTBYcU15TW9maG9NaVE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo='
|
||||||
'';
|
'';
|
||||||
|
|
||||||
services.atticd = {
|
services.atticd = {
|
||||||
|
|
|
@ -16,7 +16,7 @@ let
|
||||||
} ''
|
} ''
|
||||||
cat $configFile
|
cat $configFile
|
||||||
|
|
||||||
export ATTIC_SERVER_TOKEN_RS256_SECRET="$(${pkgs.openssl}/bin/openssl genrsa -traditional -out - 512)"
|
export ATTIC_SERVER_TOKEN_RS256_SECRET="$(${pkgs.openssl}/bin/openssl genrsa -traditional -out - 1024 | ${pkgs.coreutils}/bin/base64 -w0)"
|
||||||
export ATTIC_SERVER_DATABASE_URL="sqlite://:memory:"
|
export ATTIC_SERVER_DATABASE_URL="sqlite://:memory:"
|
||||||
${cfg.package}/bin/atticd --mode check-config -f $configFile
|
${cfg.package}/bin/atticd --mode check-config -f $configFile
|
||||||
cat <$configFile >$out
|
cat <$configFile >$out
|
||||||
|
@ -79,7 +79,7 @@ in
|
||||||
variables:
|
variables:
|
||||||
|
|
||||||
- ATTIC_SERVER_TOKEN_RS256_SECRET: The PEM-encoded version of the
|
- ATTIC_SERVER_TOKEN_RS256_SECRET: The PEM-encoded version of the
|
||||||
RS256 JWT secret. Generate it with `openssl genrsa -traditional -out private_key.pem 4096`.
|
RS256 JWT secret. Generate it with `openssl genrsa -traditional -out - 4096 | base64 -w0`.
|
||||||
'';
|
'';
|
||||||
type = types.nullOr types.path;
|
type = types.nullOr types.path;
|
||||||
default = null;
|
default = null;
|
||||||
|
@ -135,7 +135,7 @@ in
|
||||||
message = ''
|
message = ''
|
||||||
<option>services.atticd.credentialsFile</option> is not set.
|
<option>services.atticd.credentialsFile</option> is not set.
|
||||||
|
|
||||||
Run `openssl genrsa -traditional -out private_key.pem 4096` and create a file with the following contents:
|
Run `openssl genrsa -traditional -out private_key.pem 4096 | base64 -w0` and create a file with the following contents:
|
||||||
|
|
||||||
ATTIC_SERVER_TOKEN_RS256_SECRET="output from command"
|
ATTIC_SERVER_TOKEN_RS256_SECRET="output from command"
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ allowed-hosts = []
|
||||||
|
|
||||||
# JWT signing token
|
# JWT signing token
|
||||||
#
|
#
|
||||||
# Set this to the PEM encoding of some random data.
|
# Set this to the base64-encoded, then PEM encoding of an RSA key.
|
||||||
# You can also set it via the `ATTIC_SERVER_TOKEN_RS256_SECRET` environment
|
# You can also set it via the `ATTIC_SERVER_TOKEN_RS256_SECRET` environment
|
||||||
# variable.
|
# variable.
|
||||||
token-rs256-secret = "%token_rs256_secret%"
|
token-rs256-secret = "%token_rs256_secret%"
|
||||||
|
|
|
@ -26,7 +26,7 @@ const XDG_PREFIX: &str = "attic";
|
||||||
/// This is useful for deploying to certain application platforms like Fly.io
|
/// This is useful for deploying to certain application platforms like Fly.io
|
||||||
const ENV_CONFIG_BASE64: &str = "ATTIC_SERVER_CONFIG_BASE64";
|
const ENV_CONFIG_BASE64: &str = "ATTIC_SERVER_CONFIG_BASE64";
|
||||||
|
|
||||||
/// Environment variable storing the PEM-encoded RS256 JWT secret.
|
/// Environment variable storing the base64 encoded, then PEM-encoded RS256 JWT secret.
|
||||||
const ENV_TOKEN_RS256_SECRET: &str = "ATTIC_SERVER_TOKEN_RS256_SECRET";
|
const ENV_TOKEN_RS256_SECRET: &str = "ATTIC_SERVER_TOKEN_RS256_SECRET";
|
||||||
|
|
||||||
/// Environment variable storing the database connection string.
|
/// Environment variable storing the database connection string.
|
||||||
|
|
|
@ -11,7 +11,7 @@ attic = { path = "../attic", default-features = false }
|
||||||
base64 = "0.21.2"
|
base64 = "0.21.2"
|
||||||
chrono = "0.4.24"
|
chrono = "0.4.24"
|
||||||
displaydoc = "0.2.4"
|
displaydoc = "0.2.4"
|
||||||
jsonwebtoken = "9.1.0"
|
jsonwebtoken = { version = "9.1.0", features = ["use_pem"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
regex = "1.8.3"
|
regex = "1.8.3"
|
||||||
serde = "1.0.163"
|
serde = "1.0.163"
|
||||||
|
|
|
@ -93,6 +93,7 @@ pub use jsonwebtoken::{DecodingKey, EncodingKey};
|
||||||
use rsa::pkcs1::{DecodeRsaPrivateKey, EncodeRsaPublicKey};
|
use rsa::pkcs1::{DecodeRsaPrivateKey, EncodeRsaPublicKey};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::{serde_as, BoolFromInt};
|
use serde_with::{serde_as, BoolFromInt};
|
||||||
|
use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine};
|
||||||
|
|
||||||
use attic::cache::{CacheName, CacheNamePattern};
|
use attic::cache::{CacheName, CacheNamePattern};
|
||||||
|
|
||||||
|
@ -272,8 +273,14 @@ pub enum Error {
|
||||||
/// JWT error: {0}
|
/// JWT error: {0}
|
||||||
TokenError(jsonwebtoken::errors::Error),
|
TokenError(jsonwebtoken::errors::Error),
|
||||||
|
|
||||||
|
/// Base64 decode error: {0}
|
||||||
|
Base64Error(base64::DecodeError),
|
||||||
|
|
||||||
/// RSA Key error: {0}
|
/// RSA Key error: {0}
|
||||||
RsaKeyError(rsa::pkcs1::Error),
|
RsaKeyError(rsa::pkcs1::Error),
|
||||||
|
|
||||||
|
/// Failure decoding the base64 layer of the base64 encoded PEM
|
||||||
|
Utf8Error(std::str::Utf8Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
|
@ -285,7 +292,7 @@ impl Token {
|
||||||
validation.validate_nbf = true;
|
validation.validate_nbf = true;
|
||||||
// validation.set_issuer(&[ctx.config.flakehub_jwt_bound_issuer.clone()]);
|
// validation.set_issuer(&[ctx.config.flakehub_jwt_bound_issuer.clone()]);
|
||||||
// validation.set_audience(&[ctx.config.jwt_bound_audience.clone()]);
|
// validation.set_audience(&[ctx.config.jwt_bound_audience.clone()]);
|
||||||
validation.set_required_spec_claims(&["exp", "nbf", "aud", "iss", "sub"]);
|
//validation.set_required_spec_claims(&["exp", "nbf", "aud", "iss", "sub"]);
|
||||||
|
|
||||||
jsonwebtoken::decode::<JWTClaims<TokenClaims>>(token, key, &validation)
|
jsonwebtoken::decode::<JWTClaims<TokenClaims>>(token, key, &validation)
|
||||||
.map_err(Error::TokenError)
|
.map_err(Error::TokenError)
|
||||||
|
@ -314,7 +321,8 @@ impl Token {
|
||||||
|
|
||||||
/// Encodes the token.
|
/// Encodes the token.
|
||||||
pub fn encode(&self, key: &jsonwebtoken::EncodingKey) -> Result<String> {
|
pub fn encode(&self, key: &jsonwebtoken::EncodingKey) -> Result<String> {
|
||||||
let header = jsonwebtoken::Header::default();
|
let mut header = jsonwebtoken::Header::default();
|
||||||
|
header.alg = Algorithm::RS256;
|
||||||
jsonwebtoken::encode(&header, &self.0, key).map_err(Error::TokenError)
|
jsonwebtoken::encode(&header, &self.0, key).map_err(Error::TokenError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,14 +428,17 @@ impl CachePermission {
|
||||||
|
|
||||||
impl StdError for Error {}
|
impl StdError for Error {}
|
||||||
|
|
||||||
pub fn decode_token_rs256_secret(secret: &str) -> Result<(EncodingKey, DecodingKey)> {
|
pub fn decode_token_rs256_secret(s: &str) -> Result<(EncodingKey, DecodingKey)> {
|
||||||
|
let decoded = BASE64_STANDARD.decode(s).map_err(Error::Base64Error)?;
|
||||||
|
let secret = std::str::from_utf8(&decoded).map_err(Error::Utf8Error)?;
|
||||||
|
|
||||||
let private_key = rsa::RsaPrivateKey::from_pkcs1_pem(secret).map_err(Error::RsaKeyError)?;
|
let private_key = rsa::RsaPrivateKey::from_pkcs1_pem(secret).map_err(Error::RsaKeyError)?;
|
||||||
let public_key = private_key.to_public_key();
|
let public_key = private_key.to_public_key();
|
||||||
let public_pkcs1_pem = public_key
|
let public_pkcs1_pem = public_key
|
||||||
.to_pkcs1_pem(rsa::pkcs1::LineEnding::LF)
|
.to_pkcs1_pem(rsa::pkcs1::LineEnding::LF)
|
||||||
.map_err(Error::RsaKeyError)?;
|
.map_err(Error::RsaKeyError)?;
|
||||||
|
|
||||||
let encoding_key = EncodingKey::from_rsa_pem(secret.as_bytes()).map_err(Error::TokenError)?;
|
let encoding_key = EncodingKey::from_rsa_pem(&secret.as_bytes()).map_err(Error::TokenError)?;
|
||||||
let decoding_key =
|
let decoding_key =
|
||||||
DecodingKey::from_rsa_pem(public_pkcs1_pem.as_bytes()).map_err(Error::TokenError)?;
|
DecodingKey::from_rsa_pem(public_pkcs1_pem.as_bytes()).map_err(Error::TokenError)?;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue