/*
* Copyright 2015-2017 Amazon.com, Inc. or its affiliates. All Rights
* Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is
* distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either
* express or implied. See the License for the specific language
* governing
* permissions and limitations under the License.
*/
package com.amazonaws.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
/**
* Starts a new EC2 Metadata server instance with given address and port number.
*
*/
public class EC2MetadataUtilsServer {
private ServerSocket server;
public EC2MetadataUtilsServer(String address, int port)
throws UnknownHostException, IOException {
server = new ServerSocket(port, 1, InetAddress.getByName(address));
}
public void start()
throws UnknownHostException, IOException {
Thread thread = new Thread() {
@Override
public void run() {
try {
startServer();
} catch (IOException exception) {
if ((exception instanceof SocketException)
&& (exception.getMessage().equals("Socket closed"))) {
return;
}
throw new RuntimeException("BOOM", exception);
}
}
};
thread.setDaemon(true);
thread.start();
}
public void stop() throws IOException {
if (server != null) {
server.close();
}
}
public int getLocalPort() {
return server.getLocalPort();
}
private void startServer() throws IOException {
while (true) {
Socket sock = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(
sock.getInputStream()));
PrintWriter writer = new PrintWriter(sock.getOutputStream());
handleConnection(reader, writer);
writer.close();
reader.close();
sock.close();
}
}
private void handleConnection(BufferedReader input,
PrintWriter output) throws IOException {
String line = input.readLine();
if (line == null) {
return;
}
String[] parts = line.split(" ");
if (parts.length != 3) {
throw new RuntimeException("Bogus request: " + line);
}
if (!"GET".equals(parts[0])) {
throw new RuntimeException("Bogus verb: " + line);
}
ignoreRequest(input);
String path = parts[1];
if (path.equals("/latest/meta-data/iam/info")) {
outputIamInfo(output);
} else if (path.equals("/latest/meta-data/iam/security-credentials")) {
outputIamCredList(output);
} else if (path
.startsWith("/latest/meta-data/iam/security-credentials/")) {
outputIamCred(output);
} else if (path.equals("/latest/dynamic/instance-identity/document")) {
outputInstanceInfo(output);
} else {
throw new RuntimeException("Unknown path: " + path);
}
}
private void ignoreRequest(BufferedReader input) throws IOException {
while (true) {
String line = input.readLine();
if (line == null) {
throw new RuntimeException("Unexpected end of input");
}
if (line.length() == 0) {
return;
}
}
}
private void outputIamInfo(PrintWriter output) throws IOException {
String payload =
"{"
+ "\"Code\":\"Success\","
+ "\"LastUpdated\":\"2014-04-07T08:18:41Z\","
+ "\"InstanceProfileArn\":\"foobar\","
+ "\"InstanceProfileId\":\"moobily\","
+ "\"NewFeature\":12345"
+ "}";
output.println("HTTP/1.1 200 OK");
output.println("Connection: close");
output.println("Content-Length: " + payload.length());
output.println();
output.print(payload);
output.flush();
}
private void outputIamCredList(PrintWriter output)
throws IOException {
String payload = "test1\ntest2";
output.println("HTTP/1.1 200 OK");
output.println("Connection: close");
output.println("Content-Length: " + payload.length());
output.println();
output.print(payload);
output.flush();
}
private void outputIamCred(PrintWriter output) throws IOException {
String payload =
"{"
+ "\"Code\":\"Success\","
+ "\"LastUpdated\":\"2014-04-07T08:18:41Z\","
+ "\"Type\":\"AWS-HMAC\","
+ "\"AccessKeyId\":\"foobar\","
+ "\"SecretAccessKey\":\"moobily\","
+ "\"Token\":\"beebop\","
+ "\"Expiration\":\"2014-04-08T23:16:53Z\""
+ "}";
output.println("HTTP/1.1 200 OK");
output.println("Connection: close");
output.println("Content-Length: " + payload.length());
output.println();
output.print(payload);
output.flush();
}
private void outputInstanceInfo(PrintWriter output)
throws IOException {
String payload = constructInstanceInfo();
output.println("HTTP/1.1 200 OK");
output.println("Connection: close");
output.println("Content-Length: " + payload.length());
output.println();
output.print(payload);
output.flush();
}
protected String constructInstanceInfo() {
return "{"
+ "\"pendingTime\":\"2014-08-07T22:07:46Z\","
+ "\"instanceType\":\"m1.small\","
+ "\"imageId\":\"ami-a49665cc\","
+ "\"instanceId\":\"i-6b2de041\","
+ "\"billingProducts\":[\"foo\"],"
+ "\"architecture\":\"x86_64\","
+ "\"accountId\":\"599169622985\","
+ "\"kernelId\":\"aki-919dcaf8\","
+ "\"ramdiskId\":\"baz\","
+ "\"region\":\"us-east-1\","
+ "\"version\":\"2010-08-31\","
+ "\"availabilityZone\":\"us-east-1b\","
+ "\"privateIp\":\"10.201.215.38\","
+ "\"devpayProductCodes\":[\"bar\"]"
+ "}";
}
}