Skip to content

Allow importing multiple ssh keys when configuring users#3274

Open
mchf wants to merge 25 commits intomasterfrom
multiple_ssh_keys
Open

Allow importing multiple ssh keys when configuring users#3274
mchf wants to merge 25 commits intomasterfrom
multiple_ssh_keys

Conversation

@mchf
Copy link
Contributor

@mchf mchf commented Mar 13, 2026

Problem

Currently we allow to import only one ssh key for root user. We are asked to be able to 1) import multiple keys for root 2) as well for common user

Solution

  • intoduced sshPublicKeys profile / config attribute which accepts list of public keys
  • in case of root original sshPublicKey attribute is kept for backward compatibility. Internally sshPublicKey and sshPublicKeys are merged together
  • change in web UI was not requested for now

@mchf mchf force-pushed the multiple_ssh_keys branch from a0f394b to 33becb5 Compare March 13, 2026 08:38
@mchf mchf force-pushed the multiple_ssh_keys branch from 33becb5 to c843ba0 Compare March 13, 2026 08:46
@mchf mchf requested a review from imobachgs March 13, 2026 08:46
@mchf mchf force-pushed the multiple_ssh_keys branch 2 times, most recently from 80862f5 to 4b11547 Compare March 13, 2026 08:54
@mchf mchf force-pushed the multiple_ssh_keys branch from 4b11547 to 8213b9a Compare March 13, 2026 08:56
@mchf mchf force-pushed the multiple_ssh_keys branch 3 times, most recently from a03b61a to df01193 Compare March 13, 2026 09:58
@mchf mchf force-pushed the multiple_ssh_keys branch from df01193 to 33b371e Compare March 13, 2026 09:59
Copy link
Contributor

@imobachgs imobachgs left a comment

Choose a reason for hiding this comment

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

This PR does not implement exactly what we agreed on. We expected to:

  • Extend the existing sshPublicKey attribute to support a single string or an array of strings.
  • Add an alias sshPublicKeys.

@mchf mchf force-pushed the multiple_ssh_keys branch from 852f64c to 13d46a7 Compare March 13, 2026 14:06
@mchf mchf force-pushed the multiple_ssh_keys branch from bdcc0ca to 84ed964 Compare March 13, 2026 14:46
@mchf mchf force-pushed the multiple_ssh_keys branch from 84ed964 to 4a6f56d Compare March 13, 2026 14:55
ssh_keys
.iter()
.try_for_each(|ssh_key| -> Result<(), service::Error> {
writeln!(authorized_keys_file, "{}", ssh_key.trim())?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Would not be easier to just "join" all the keys and write them at once?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

well I'd need to trim them anyway. Is there any benefit? I don't expect that many keys that it could get out of fs cache and cause speed issues

Copy link
Contributor

Choose a reason for hiding this comment

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

Me neither, but it would be more readable in my opinion. And you only write to disk in one shot. But it is fine as it is.

assert!(!root_with_ssh_key_config.is_empty());

let root_with_ssh_keys = RootUserConfig {
ssh_public_key: Some(StringOrList::List(vec!["12345678".to_string()])),
Copy link
Contributor

Choose a reason for hiding this comment

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

I would define a StringOrList::from_vec (or something similar). But it is not important, as it is only used in the tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

well i tend to not add code only due to tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

As you prefer. But if it helps to make the tests easier to understand and maintain...

@config = result.config
end

def basic_user_info(user)
Copy link
Contributor

Choose a reason for hiding this comment

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

To be honest, I do not see the point of moving these two assigments to a separate function. But I can live with that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it was because of rubocop ... coplained for complexity.

#[serde(skip_serializing_if = "Option::is_none")]
pub ssh_public_key: Option<String>,
#[serde(alias = "ssh_public_keys")]
#[schema(inline)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you need this schema(inline)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OpenAPI otherwise complains on StringOnList ... another option was do a nontrivial update in web server, the components method.

Copy link
Contributor

Choose a reason for hiding this comment

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

But does it generate the proper OpenAPI specification? Just asking.

Copy link
Contributor

@imobachgs imobachgs Mar 14, 2026

Choose a reason for hiding this comment

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

Yes, it does, you can check it by running the command cargo xtask openapi.

          {
            "type": "object",
            "properties": {
              "sshPublicKey": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  }
                ],
                "description": "Root SSH public key"
              }
            }
          }

@mchf mchf force-pushed the multiple_ssh_keys branch 2 times, most recently from 7275c11 to 830664a Compare March 13, 2026 18:27
@mchf mchf requested a review from imobachgs March 13, 2026 18:37
@mchf mchf force-pushed the multiple_ssh_keys branch from 830664a to 15cc2eb Compare March 13, 2026 18:41
.as_ref()
.map(|k| k.to_vec())
.unwrap_or_default();
// do some magic about user's home dir path or stay
Copy link
Contributor

Choose a reason for hiding this comment

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

I would say it is fine. Perhaps we could move the string to a const, but that's all.

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.

2 participants