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
3 changes: 1 addition & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ jobs:
run: |
cargo build --release
- name: tar
run: |
tar --directory=target/release -cf archive.tar.gz nitrogen.exe
run: tar --directory=target/release -cf archive.tar.gz nitrogen.exe
- name: upload
run: |
$id = gh api -H "Accept: application/vnd.github+json" /repos/capeprivacy/nitrogen/releases/tags/${{ github.ref_name }} --jq .id
Expand Down
14 changes: 14 additions & 0 deletions examples/vault/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM vault:latest


RUN apk --no-cache add socat=1.7.4.1-r1

COPY config.hcl config.hcl

COPY run.sh ./
RUN ["chmod", "+x", "./run.sh"]

COPY app.sh ./
RUN ["chmod", "+x", "./app.sh"]

CMD ["/bin/sh", "/run.sh"]
15 changes: 15 additions & 0 deletions examples/vault/Dockerfile.tls
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM vault:latest


RUN apk --no-cache add socat=1.7.4.1-r1

COPY config-tls.hcl config-tls.hcl
COPY vault.key vault.pem ./

COPY run.sh ./
RUN ["chmod", "+x", "./run.sh"]

COPY app-tls.sh ./app.sh
RUN ["chmod", "+x", "./app.sh"]

CMD ["/bin/sh", "/run.sh"]
124 changes: 124 additions & 0 deletions examples/vault/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Vault Example

## Requirements

- vault CLI (see [here](https://developer.hashicorp.com/vault/docs/install) for installation instructions)

## Deploy Vault

```
$ nitrogen setup vault-nitro ~/.ssh/id_rsa.pub
```

```
$ nitrogen build examples/vault
```

```
$ nitrogen deploy vault-nitro ~/.ssh/id_rsa
```

After the last command you should see something like:

```
...
2022-11-24T19:23:19.595376Z INFO nitrogen::commands::deploy: EIF is now running public_dns="ec2-54-159-199-57.compute-1.amazonaws.com"
2022-11-24T19:23:19.595512Z INFO nitrogen::commands::deploy: Check enclave status...
2022-11-24T19:23:20.159233Z INFO nitrogen::commands::deploy: Enclave up and running!
```

## Setup Vault

Here we've deployed Vault in production mode so it takes a few more steps to fully set up Vault.

First, set the address of the ec2 instance:

```
$ export VAULT_ADDR="ec2-54-159-199-57.compute-1.amazonaws.com"
```

Next initialize vault:

```
$ vault operator init
```

Should see some output like:

```
Unseal Key 1: J6jRd1lZ7eU+wmBmtE4OsmymVtWfPmpGnh7z/o4e68JG
Unseal Key 2: cLZnWKAt2KxSpsMxNAOZ05Pcv1XmxFugcrzh3fNp+GCw
Unseal Key 3: quW9NrKUdrLcpYCnHRqUORXH+VjX9O8QwHafQETtVxcU
Unseal Key 4: ZI9pTMq7KEy7e2zC+AJx5iSANTBQA4ts0UxJeh7EyEqS
Unseal Key 5: F5lI1mjyR7h24lDtY95uBLLRs+mupcTvJBRl+aDtSd4a

Initial Root Token: hvs.FDnNk0XLP7jv2g18UnMkN3mi

Vault initialized with 5 key shares and a key threshold of 3. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.

Vault does not store the generated root key. Without at least 3 keys to
reconstruct the root key, Vault will remain permanently sealed!

It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information.
```

Then for 3 of the key shares call the following:

```
$ vault operator unseal <KEY SHARE>
```

Finally log in with the root token:

```
$ vault login <ROOT TOKEN>
```

## Store Keys

To store keys in production mode we must first set up a secrets engine:

```
$ vault secrets enable kv
```

And then we can store and retrieve secrets:

```
$ vault kv put -mount=kv sec foo=bar
```

```
$ vault kv get -mount=kev sec
```

## TLS

**Note: reading the [nginx tls example](../nginx-tls/README.md) could be helpful for some more background**

With some additional setup we can enable TLS.

First, generate the certificate and key with `mkcert`:

```
$ mkcert -cert-file vault.pem -key-file vault.key <INSTANCE HOST NAME>
$ cp vault.pem vault.key examples/vault
```

```
$ nitrogen build examples/vault -d Dockerfile.tls
```

```
$ nitrogen deploy vault-nitro ~/.ssh/id_rsa
```

```
$ export VAULT_ADDR="https://ec2-54-159-199-57.compute-1.amazonaws.com"
```

Then you can follow the rest of the sets from above but this is using TLS!
3 changes: 3 additions & 0 deletions examples/vault/app-tls.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

vault server -config=config-tls.hcl
3 changes: 3 additions & 0 deletions examples/vault/app.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

vault server -config=config.hcl
14 changes: 14 additions & 0 deletions examples/vault/config-tls.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
backend "file" {
path = "/vault/file"
default_lease_ttl = "168h"
max_lease_ttl = "720h"
}

listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "vault.pem"
tls_key_file = "vault.key"
}

api_addr = "http://0.0.0.0:8200"
cluster_addr = "https://0.0.0.0:8201"
13 changes: 13 additions & 0 deletions examples/vault/config.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
backend "file" {
path = "/vault/file"
default_lease_ttl = "168h"
max_lease_ttl = "720h"
}

listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = "true"
}

api_addr = "http://0.0.0.0:8200"
cluster_addr = "https://0.0.0.0:8201"
8 changes: 8 additions & 0 deletions examples/vault/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh

ip addr add 127.0.0.1/32 dev lo
ip link set dev lo up

socat vsock-listen:5000,reuseaddr,fork tcp-connect:127.0.0.1:8200 &

sh ./app.sh
24 changes: 19 additions & 5 deletions src/bin/nitrogen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,13 @@ enum Commands {
Build {
/// Dockerfile directory
dockerfile_dir: String,

/// Output EIF location
#[arg(short, long, default_value_t = String::from("Dockerfile"))]
dockerfile_name: String,

/// Output EIF location
#[arg(short, long, default_value_t = String::from("./nitrogen.eif"))]
#[arg(short, long, default_value_t = String::from("nitrogen.eif"))]
eif: String,
},

Expand All @@ -62,7 +67,7 @@ enum Commands {
/// Name of a Nitrogen-generated CloudFormation stack
name: String,
/// Filepath to EIF
#[arg(short, long, default_value_t = String::from("./nitrogen.eif"))]
#[arg(short, long, default_value_t = String::from("nitrogen.eif"))]
eif: String,
/// Filepath to SSH key for the instance
ssh_key: String,
Expand Down Expand Up @@ -164,10 +169,14 @@ async fn main() -> Result<(), Error> {
}
Commands::Build {
dockerfile_dir,
dockerfile_name,
eif,
} => {
info!(dockerfile_dir, "Building EIF from dockerfile.");
let out = build(&dockerfile_dir, &eif).await?;
info!(
dockerfile_dir,
dockerfile_name, "Building EIF from dockerfile."
);
let out = build(&dockerfile_dir, &dockerfile_name, &eif).await?;
debug!(docker_output=?out, "Docker output:");
Ok(())
}
Expand Down Expand Up @@ -258,7 +267,12 @@ async fn main() -> Result<(), Error> {
// TODO should save this somewhere else than their current directory
let eif_path = &format!("{}.eif", service);

build(&proj_dir.to_str().unwrap().to_string(), eif_path).await?;
build(
&proj_dir.to_str().unwrap().to_string(),
&"Dockerfile".to_string(),
eif_path,
)
.await?;

info!("Sleeping for 20s to give ec2 instance a chance to boot...");
tokio::time::sleep(Duration::from_secs(20)).await;
Expand Down
11 changes: 8 additions & 3 deletions src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ use tokio::process::Command;
use tracing::{info, instrument};

#[instrument(level = "debug")]
pub async fn build(dockerfile_dir: &String, eif_name: &String) -> Result<Output, Error> {
pub async fn build(
dockerfile_dir: &String,
dockerfile_name: &String,
eif_name: &String,
) -> Result<Output, Error> {
let dockerdir = PathBuf::from(dockerfile_dir);
let mut dockerfile_path = PathBuf::from(dockerfile_dir);
dockerfile_path.push("Dockerfile");
dockerfile_path.push(dockerfile_name);

let out = Command::new("docker")
.args([
Expand Down Expand Up @@ -61,7 +65,8 @@ pub async fn build(dockerfile_dir: &String, eif_name: &String) -> Result<Output,
stderr_str
)));
} else {
info!("EIF written to {}/{}.", eif_dir, &eif_name);
let path_buf = cwd.join(eif_name);
info!("EIF written to {}", path_buf.display());
}
Ok(out)
}
2 changes: 1 addition & 1 deletion src/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub(crate) fn describe_enclave(ssh_key: &str, url: &str) -> Result<Value, Error>
}

fn check_enclave_status(ssh_key: &str, url: &str) -> Result<(), Error> {
info!("Check enclave status...");
info!("Checking enclave status...");

match describe_enclave(ssh_key, url)?.get("State") {
// According to the docs, the state is either "running" or "terminating"
Expand Down