【问题标题】:Setting user credentials on aws instance using jclouds使用 jclouds 在 aws 实例上设置用户凭据
【发布时间】:2015-10-24 18:50:00
【问题描述】:

我正在尝试使用 jclouds 1.9.0 创建一个 aws 实例,然后在其上运行一个脚本(通过 ssh)。我正在按照示例找到here,但是当客户端(java 程序)尝试在实例上连接时出现身份验证失败错误。 AWS 控制台显示该实例已启动并正在运行。

该示例尝试创建一个 LoginCrendentials 对象

String user = System.getProperty("user.name");
String privateKey = Files.toString(new File(System.getProperty("user.home") + "/.ssh/id_rsa"), UTF_8);
return LoginCredentials.builder().user(user).privateKey(privateKey).build();

后者用于 ssh 客户端

responses = compute.runScriptOnNodesMatching(
                inGroup(groupName),             // predicate used to select nodes
                exec(command),                  // what you actually intend to run
                overrideLoginCredentials(login) // use my local user & ssh key
                        .runAsRoot(false)       // don't attempt to run as root (sudo)
                        .wrapInInitScript(false));

使用以下命令将一些登录信息注入实例

Statement bootInstructions = AdminAccess.standard();
templateBuilder.options(runScript(bootInstructions));

由于我在 Windows 机器上创建 LoginCrendentials '失败',因此我将其代码更改为

String user = "ec2-user";
String privateKey = "-----BEGIN RSA PRIVATE KEY-----.....-----END RSA PRIVATE KEY-----";
return  LoginCredentials.builder().user(user).privateKey(privateKey).build();

我还按照"EC2: In Depth" 指南中的描述在构建模板时定义凭据,但没有运气。

另一种方法是按如下方式构建实例并注入密钥对,但这意味着我需要将 ssh 密钥存储在我的 AWS 控制台中,目前情况并非如此,并且还会破坏运行脚本的功能(通过ssh) 因为我无法从RunningInstance 对象推断出NodeMetadata

RunInstancesOptions options = RunInstancesOptions.Builder.asType("t2.micro").withKeyName(keypair).withSecurityGroup(securityGroup).withUserData(script.getBytes());

有什么建议吗??

注意:虽然我目前正在 aws 上对此进行测试,但我希望尽可能地使代码与提供程序分离。

2015 年 10 月 26 日更新

基于@Ignasi Barrera answer,我通过在创建bootInstructions 时添加.init(new MyAdminAccessConfiguration()) 来更改我的实现

Statement bootInstructions = AdminAccess.standard().init(new MyAdminAccessConfiguration());
templateBuilder.options(runScript(bootInstructions));

MyAdminAccessConfiguration 是我自己实现的 AdminAccessConfiguration 接口,正如@Ignasi Barrera 所描述的那样。

【问题讨论】:

    标签: ssh amazon-ec2 jclouds


    【解决方案1】:

    我认为这个问题取决于 jclouds 代码在 Windows 机器上运行的事实,而 jclouds 在默认情况下会做出一些 Unix 假设。

    这里有两个不同的东西:首先,AdminAccess.standard() 用于在部署的节点启动后配置用户,然后传递给运行脚本方法的LoginCredentials 对象用于对用户进行身份验证使用前面的语句创建的。

    这里的问题是AdminAccess.standard() 读取“当前用户”信息并假定为 Unix 系统。该用户信息由 this Default class 提供,在您的情况下,我很确定它将回退到 catch 块并返回自动生成的 SSH 密钥对。这意味着,AdminAccess.standard() 正在使用自动生成的(随机)SSH 密钥在节点中创建用户,但您正在构建的 LoginCredentials 与这些密钥不匹配,因此身份验证失败。

    由于AdminAccess 实体是不可变的,解决此问题的更好、更简洁的方法是创建您自己的AdminAccessConfiguration interface 实现。您可以复制整个 Default 类并更改 Unix 特定位以适应 Windows 机器中的 SSH 设置。一旦你有了实现类,你可以通过创建一个 Guice 模块并将它传​​递到创建 jclouds 上下文时提供的模块列表来注入它。比如:

    // Create the custom module to inject your implementation
    Module windowsAdminAccess = new AbstractModule() {
       @Override protected void configure() {
          bind(AdminAccessConfiguration.class).to(YourCustomWindowsImpl.class).in(Scopes.SINGLETON);
       }
    };
    
    // Provide the module in the module list when creating the context
    ComputeServiceContext context = ContextBuilder.newBuilder("aws-ec2")
       .credentials("api-key", "api-secret")
       .modules(ImmutableSet.<Module> of(windowsAdminAccess, new SshjSshClientModule()))
       .buildView(ComputeServiceContext.class);
    

    【讨论】:

    • 我在bind(.... 收到编译器错误“AdminAccessConfiguration 无法解析为变量”,有什么建议吗?或者您可以指出我的任何资源?
    • 这是一个错字。 AdminAccessConfiguration 缺少 .class。我已经编辑了帖子。
    最近更新 更多