-
Notifications
You must be signed in to change notification settings - Fork 11.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[suiop] add support for deploy key automation (#17509)
## Description With this change, we can now create/recreate/delete deploy keys for our users and the private keys will be stored securely instead of on users' laptop. suiop here is just a client, all it does is authn the user and use the returned Okta token to the infra-metadata-service endpoint for ssh key generation. ## Test plan Manually tested, for example, to create a deploy key: `suiop ci key create --repo-name suiop-test` ``` Public Key: ------------------------- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPn4Rj84+AGRPJNx2QVV7R8gURJHxicC0YW1UKWLOlz0 pulumi_automation_deploy_key ------------------------- Please add the public key above to your repository suiop-test via the link below: https://github.com/MystenLabs/suiop-test/settings/keys/new ``` A new key will be created automatically and user will be prompted to put the corresponding pubkey to their private repo so that we can have control over it. --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK:
- Loading branch information
1 parent
ef49d37
commit aa86996
Showing
9 changed files
with
207 additions
and
17 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use crate::cli::lib::{get_api_server, get_oauth_token}; | ||
use anyhow::Result; | ||
|
||
use clap::Parser; | ||
use colored::Colorize; | ||
use tracing::debug; | ||
|
||
#[derive(Parser, Debug)] | ||
pub struct KeyArgs { | ||
#[command(subcommand)] | ||
action: KeyAction, | ||
} | ||
|
||
#[derive(clap::Subcommand, Debug)] | ||
pub enum KeyAction { | ||
#[command(name = "create")] | ||
Create { | ||
#[arg(short, long)] | ||
repo_name: String, | ||
}, | ||
#[command(name = "recreate")] | ||
ReCreate { | ||
#[arg(short, long)] | ||
repo_name: String, | ||
}, | ||
#[command(name = "delete")] | ||
Delete { | ||
#[arg(short, long)] | ||
repo_name: String, | ||
}, | ||
} | ||
|
||
#[derive(serde::Serialize)] | ||
struct KeyRequest { | ||
repo_name: String, | ||
} | ||
|
||
const ENDPOINT: &str = "/automation/deploy-key"; | ||
|
||
pub async fn key_cmd(args: &KeyArgs) -> Result<()> { | ||
let token = get_oauth_token().await?; | ||
debug!("token: {}", token.access_token); | ||
send_key_request(&token.access_token, &args.action).await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
#[derive(serde::Deserialize)] | ||
struct KeyResponse { | ||
pub_key: Option<String>, | ||
message: String, | ||
} | ||
|
||
async fn send_key_request(token: &str, action: &KeyAction) -> Result<()> { | ||
let req = generate_key_request(token, action); | ||
|
||
println!( | ||
"Processing request... Please wait patiently. It may take about 20 seconds to complete." | ||
); | ||
let resp = req.send().await?; | ||
debug!("resp: {:?}", resp); | ||
|
||
let status = resp.status(); | ||
let json_resp = resp.json::<KeyResponse>().await?; | ||
|
||
if status.is_success() { | ||
match action { | ||
KeyAction::Create { repo_name } | KeyAction::ReCreate { repo_name } => { | ||
if let Some(pubkey) = json_resp.pub_key { | ||
let add_key_link = format!( | ||
"https://github.com/MystenLabs/{}/settings/keys/new", | ||
repo_name | ||
); | ||
println!( | ||
r#"Public Key: | ||
------------------------- | ||
{} | ||
------------------------- | ||
Please add the public key above to your repository {} via the link below: | ||
{}"#, | ||
pubkey.yellow(), | ||
repo_name.bright_purple(), | ||
add_key_link.yellow() | ||
) | ||
} else { | ||
return Err(anyhow::anyhow!( | ||
"Failed to get public key for repo {}.", | ||
repo_name.bright_purple() | ||
)); | ||
} | ||
} | ||
KeyAction::Delete { repo_name } => { | ||
println!("Key for repo {} deleted", repo_name.bright_purple()); | ||
} | ||
} | ||
Ok(()) | ||
} else { | ||
Err(anyhow::anyhow!( | ||
"Failed to manage keys: {} - {}", | ||
status, | ||
json_resp.message.yellow() | ||
)) | ||
} | ||
} | ||
|
||
fn generate_headers_with_auth(token: &str) -> reqwest::header::HeaderMap { | ||
let mut headers = reqwest::header::HeaderMap::new(); | ||
headers.insert( | ||
reqwest::header::AUTHORIZATION, | ||
reqwest::header::HeaderValue::from_str(&format!("Bearer {}", token)).unwrap(), | ||
); | ||
headers | ||
} | ||
|
||
fn generate_key_request(token: &str, action: &KeyAction) -> reqwest::RequestBuilder { | ||
let client = reqwest::Client::new(); | ||
let api_server = get_api_server(); | ||
let full_url = format!("{}{}", api_server, ENDPOINT); | ||
debug!("full_url: {}", full_url); | ||
let req = match action { | ||
KeyAction::Create { repo_name } => client | ||
.post(full_url) | ||
.headers(generate_headers_with_auth(token)) | ||
.json(&KeyRequest { | ||
repo_name: repo_name.to_string(), | ||
}), | ||
KeyAction::ReCreate { repo_name } => client | ||
.put(full_url) | ||
.headers(generate_headers_with_auth(token)) | ||
.json(&KeyRequest { | ||
repo_name: repo_name.to_string(), | ||
}), | ||
KeyAction::Delete { repo_name } => client | ||
.delete(full_url) | ||
.headers(generate_headers_with_auth(token)) | ||
.json(&KeyRequest { | ||
repo_name: repo_name.to_string(), | ||
}), | ||
}; | ||
debug!("req: {:?}", req); | ||
|
||
req | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
mod key; | ||
|
||
use anyhow::Result; | ||
use key::key_cmd; | ||
|
||
use clap::Parser; | ||
|
||
use self::key::KeyArgs; | ||
|
||
#[derive(Parser, Debug)] | ||
pub struct CIArgs { | ||
#[command(subcommand)] | ||
action: CIAction, | ||
} | ||
|
||
#[derive(clap::Subcommand, Debug)] | ||
pub(crate) enum CIAction { | ||
#[clap(aliases = ["k", "key"])] | ||
Keys(KeyArgs), | ||
} | ||
|
||
pub async fn ci_cmd(args: &CIArgs) -> Result<()> { | ||
match &args.action { | ||
CIAction::Keys(keys) => key_cmd(keys).await?, | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters