我正在尝试使用jclouds 1.9.0
创建一个aws实例,然后在其上运行一个脚本(通过ssh)。我正在关注示例locate 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)因为我无法从NodeMetadata
对象推断出RunningInstance
。
RunInstancesOptions options = RunInstancesOptions.Builder.asType("t2.micro").withKeyName(keypair).withSecurityGroup(securityGroup).withUserData(script.getBytes());
有什么建议吗?
注意:虽然我目前正在对aws进行测试,但我希望尽可能将代码与提供程序分离。
更新26/10/2015
基于@Ignasi Barrera answer,我在创建.init(new MyAdminAccessConfiguration())
bootInstructions
来更改了我的实施
Statement bootInstructions = AdminAccess.standard().init(new MyAdminAccessConfiguration());
templateBuilder.options(runScript(bootInstructions));
其中MyAdminAccessConfiguration
是我自己的AdminAccessConfiguration接口实现,正如@Ignasi Barrera所描述的那样。
答案 0 :(得分:1)
我认为这个问题依赖于jclouds代码在Windows机器上运行的事实,而jclouds默认会做出一些Unix假设。
这里有两个不同的东西:首先,AdminAccess.standard()
用于在部署的节点启动后配置用户,稍后传递给运行脚本方法的LoginCredentials
对象用于对使用前一个语句创建的用户进行身份验证。
这里的问题是AdminAccess.standard()
读取“当前用户”信息并假设是Unix系统。该用户信息由this Default class提供,在您的情况下,我非常确定它将回退到catch
块并返回自动生成的SSH密钥对。这意味着,AdminAccess.standard()
正在使用自动生成的(随机)SSH密钥在节点中创建用户,但您正在构建的LoginCredentials
与这些密钥不匹配,因此身份验证失败。 / p>
由于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);