Hot questions for Using Azure in azure automation

Top Java Programmings / Azure / azure automation

Question:

In this link (Create azure automation account using REST api from java) I'd asked about how to create an automation account in order to create runbook. Now, that I've created an automation account and also a runbook which is published, I want to execute(start) the runbook. In order to do so I am following this link (https://msdn.microsoft.com/en-us/library/azure/mt163849.aspx) but I am getting an error:

Server Error</h1></div>
<div id="content">
 <div class="content-container"><fieldset>
  <h2>404 - File or directory not found.</h2>
  <h3>The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable

This is the java function:

    private static int processPutRequest(URL url, byte[] data, String contentType, String keyStore, String keyStorePassword) 
    throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
       SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
       HttpsURLConnection con = null;
       con = (HttpsURLConnection) url.openConnection();
       con.setSSLSocketFactory(sslFactory);
       con.setDoOutput(true);
       con.setRequestMethod("PUT");
       con.addRequestProperty("x-ms-version", "2013-08-01");
       con.setRequestProperty("Content-Length", String.valueOf(data.length));
       con.setRequestProperty("Content-Type", contentType);

       DataOutputStream requestStream = new DataOutputStream (con.getOutputStream());
       requestStream.write(data);
       requestStream.flush();
       requestStream.close();

       System.out.println(con.getResponseMessage());

       InputStream error = ((HttpURLConnection) con).getErrorStream();

       BufferedReader br = null;
       if (error == null) {
          InputStream inputstream = con.getInputStream();
          br = new BufferedReader(new InputStreamReader(inputstream));
       } else {
          br = new BufferedReader(new InputStreamReader(error));
       }
       String response = "";
       String nachricht;
       while ((nachricht = br.readLine()) != null){
          response += nachricht;
       }
       System.out.println(response);
       return con.getResponseCode();
   }

   public static void createJobId(String keyStorePath, String keyStorePassword, String subscriptionId)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
   {
       String url = String.format("https://management.core.windows.net/%s/cloudServices/OaaSCSI6EGAZU6F6QTCK5XRVT45FKJC6RC7IQIQW3OPR7SVLE4ZPD4IQQQ-East-US/resources/automation/~/automationAccounts/xdtauto/jobs/8c3e715-9b27?api-version=2014-12-08", subscriptionId);
       String requestBody = "{ \"properties\":{ \"runbook\":{ \"name\":\"createVM\" } } }";
       int createResponseCode = processPutRequest(new URL(url), requestBody.getBytes(), "application/json", keyStorePath, keyStorePassword);
       System.out.println("JOB created :: " + createResponseCode);
   }

Answer:

@Joe's guess is correct.

Refer to the link https://msdn.microsoft.com/en-us/library/azure/mt163849.aspx . As document shown,

In Windows PowerShell, you can use the this command to create the job ID:[GUID]::NewGuid().ToString().

The GUID in C#/.NET is generated by the functuion "System.Guid.NewGuid()". In Java, UUID is the same as GUID. Refer to the UUID Class link http://docs.oracle.com/javase/8/docs/api/java/util/UUID.html, it is generated by the function "java.util.UUID.randomUUID()".

So your code should be modified as following:

public static void createJobId(String keyStorePath, String keyStorePassword, String subscriptionId)
            throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException,
            IOException {
        String automationName = <auto_account_name>;
        String jobId=java.util.UUID.randomUUID().toString();
        String url = String.format(
                "https://management.core.windows.net/%s/cloudServices/ OaaSCSI6EGAZU6F6QTCK5XRVT45FKJC6RC7IQIQW3OPR7SVLE4ZPD4IQQQ-East-US/resources/automation/~/automationAccounts/%s/jobs/%s?api-version=2014-12-08",
                subscriptionId, automationName, jobId);
        System.out.println("URL: "+url);
        String requestBody = "{ \"properties\":{ \"runbook\":{ \"name\":\"<RUNBOOK_NAME>\" } } }";
        int createResponseCode = processPutRequest(new URL(url), requestBody.getBytes(), "application/json",
                keyStorePath, keyStorePassword);
        System.out.println("JOB created :: " + createResponseCode);
    }

If you have created the runbook correctly and set up the correct runbook name in the request body, the code will run as expection and response the StatusCode 201.

However I found the other issue of the function "createRunbook" in your thread Create azure automation account using REST api from java, the element " properties/publishContentLink/uri" is required in the request body of create runbook(refer to https://msdn.microsoft.com/en-us/library/azure/mt163812.aspx).

So if the response body of create job include the information {"code":"NotFound","message":"Runbook not found."}, I suggest you to check your code and review the Runbook page on Azure Portal.

Question:

I developed a PowerShell script that installs Java Server JRE and registers the environmental variables. It works when I run it via PowerShell ISE but fails if I try to execute the PowerShell remotely. I remotely execute by attaching the script as a CSE to the desired VM via Azure Automation.

The weird part is that the remote PowerShell install shows the Environment Variables. If I open the Environment Variables GUI edit/save it then edit and save it back to the correct path it starts working (ex. edit and add a \bin and save, edit and remove \bin and save). Via local PowerShell ISE execution of my script, I don't have to do this, it just works. Am I missing some sort of registration step to get the Java Server JRE.

$solrPath = "C:\Solr"
# Get Zip file containing Java Server JRE from CDN
Invoke-WebRequest -Uri 'http://mycdn.com/Solr/Downloads/jdk1.8.0_144.zip' -OutFile C:\mydir\java.zip
Write-Output "Java Server JRE Zip file downloaded from CDN"

# Unzip Java Server JRE Directory
Expand-Archive -Path C:\mydir\java.zip -DestinationPath $solrPath -Force
Write-Output "Java Server JRE Zip file extracted"

# Set Java Path and Home Environmental Variables
# Add the PATH environment variable to point to the Java Directory Bin
$oldpath = (Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path
$newpath = "$oldpath;$solrPath\jdk1.8.0_144\jre\bin" 
Set-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH –Value $newpath
$donepath = (Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path
Write-host "Validation; new value set to $donepath"

Answer:

It ended up being an issue with another part of my script. Once I corrected that, Java installed correctly.

Question:

I am trying to create an automation account in Azure using REST API from java. Right now I am able to list images, create service using REST API from java but when I am trying to create an automation account I get the error:

   Forbidden
   <Error xmlns="http://schemas.microsoft.com/windowsazure" 
   xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
   <Code>ForbiddenError</Code>
   <Message>The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.</Message>
   </Error> 

JAVA class:

  import java.io.IOException;
  import java.net.*;
  import java.security.*;
  import java.io.*;
  import java.security.KeyManagementException;
  import java.security.NoSuchAlgorithmException;
  import java.security.KeyStoreException;
  import java.security.UnrecoverableKeyException;
  import javax.net.ssl.HttpsURLConnection;
  import javax.net.ssl.KeyManagerFactory;
  import javax.net.ssl.SSLContext;
  import javax.net.ssl.SSLSocketFactory;
  import org.apache.commons.codec.binary.Base64;

  public class AzureRest
  {
        private static KeyStore getKeyStore(String keyStoreName, String password)
throws IOException
{
    KeyStore ks = null;
    FileInputStream fis = null;
    try {
        ks = KeyStore.getInstance("JKS");
        char[] passwordArray = password.toCharArray();
        fis = new java.io.FileInputStream(keyStoreName);
        ks.load(fis, passwordArray);
        fis.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        if (fis != null) {
            fis.close();
        }
    }
    return ks;
}

    private static SSLSocketFactory getSSLSocketFactory(String keyStoreName, String password)
throws UnrecoverableKeyException, KeyStoreException, 
NoSuchAlgorithmException, KeyManagementException, IOException {

    KeyStore ks = getKeyStore(keyStoreName, password);
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
    keyManagerFactory.init(ks, password.toCharArray());

    SSLContext context = SSLContext.getInstance("TLS");
    context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());

    return context.getSocketFactory();
}

private static String getStringFromInputStream(InputStream is) {

    BufferedReader br = null;
    StringBuilder sb = new StringBuilder();

    String line;
    try {
        br = new BufferedReader(new InputStreamReader(is));
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    return sb.toString();
}

private static String processGetRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
    SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
    HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
    con.setSSLSocketFactory(sslFactory);
    con.setRequestMethod("GET");
    con.addRequestProperty("x-ms-version", "2013-08-01");
    InputStream responseStream = (InputStream) con.getContent();
    String response = getStringFromInputStream(responseStream);
    responseStream.close();
    return response;
}

private static int processPostRequest(URL url, byte[] data, String contentType, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
    SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
    HttpsURLConnection con = null;
    con = (HttpsURLConnection) url.openConnection();
    con.setSSLSocketFactory(sslFactory);
    con.setDoOutput(true);
    con.setRequestMethod("POST");
    con.addRequestProperty("x-ms-version", "2013-08-01");
    con.setRequestProperty("Content-Length", String.valueOf(data.length));
    con.setRequestProperty("Content-Type", contentType);

    DataOutputStream requestStream = new DataOutputStream (con.getOutputStream());
    requestStream.write(data);
    requestStream.flush();
    requestStream.close();

    System.out.println(con.getResponseMessage());

    InputStream error = ((HttpURLConnection) con).getErrorStream(); 

    BufferedReader br = null;
    if (error == null) {
         InputStream inputstream = con.getInputStream();
          br = new BufferedReader(new InputStreamReader(inputstream));
    } else {
        br = new BufferedReader(new InputStreamReader(error));
    }
    String response = "";
    String nachricht;
    while ((nachricht = br.readLine()) != null){
          response += nachricht;
    }
    System.out.println(response);
    return con.getResponseCode();
}

private static int processDeleteRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
    SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
    HttpsURLConnection con = null;
    con = (HttpsURLConnection) url.openConnection();
    con.setSSLSocketFactory(sslFactory);
    con.setRequestMethod("DELETE");
    con.addRequestProperty("x-ms-version", "2013-08-01");
    return con.getResponseCode();
}

public static void getLocation(String keyStorePath, String keyStorePassword, String subscriptionId)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    // List locations
    url = String.format("https://management.core.windows.net/%s/locations", subscriptionId);
    String response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
    System.out.println(response);
}

public static void createCloudService(String keyStorePath, String keyStorePassword, String subscriptionId, String cloudService)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    // Create cloud service
    String label = "Cloud service in java";
    String description = "Cloud service in java";
    String location = "East US 2";
    url = String.format("https://management.core.windows.net/%s/services/hostedservices", subscriptionId);
    String requestBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?><CreateHostedService xmlns=\"http://schemas.microsoft.com/windowsazure\"><ServiceName>%s</ServiceName><Label>%s</Label><Description>%s</Description><Location>%s</Location></CreateHostedService>";
    requestBody = String.format(requestBody, cloudService, Base64.encodeBase64String(label.getBytes()), description, location);
    int createResponseCode = processPostRequest(new URL(url), requestBody.getBytes(), "application/xml", keyStorePath, keyStorePassword);
    System.out.println("Created service: " + createResponseCode);
}

public static void deleteCloudService(String keyStorePath, String keyStorePassword, String subscriptionId, String cloudService)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    //Delete cloud service
    url = String.format("https://management.core.windows.net/%s/services/hostedservices/%s", subscriptionId, cloudService);
    int deleteResponseCode = processDeleteRequest(new URL(url), keyStorePath, keyStorePassword);
    System.out.println(deleteResponseCode);
}

public static void listImages(String keyStorePath, String keyStorePassword, String subscriptionId)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    String response = "";
    // List Images
    url = String.format("https://management.core.windows.net/%s/services/images", subscriptionId);
    response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
    System.out.println(response);
}

public static void listAutomationAccounts(String keyStorePath, String keyStorePassword, String subscriptionId)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    String response = "";
    // List automation accounts in a cloud service
    url = String.format("https://management.core.windows.net/%s/cloudServices/OaaSCSI6EGAZU6F6QTCK5XRVT45FKJC6RC7IQIQW3OPR7SVLE4ZPD4IQQQ-East-US?resourceType=AutomationAccount&detailLevel=Full&resourceProviderNamespace=automation", subscriptionId);
    response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
    System.out.println(response);
}

public static void checkCloudServiceAvailability(String keyStorePath, String keyStorePassword, String subscriptionId, String cloudService)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    String response = "";

    // Check service name availability
    url = String.format("https://management.core.windows.net/%s/services/hostedservices/operations/isavailable/%s", subscriptionId, cloudService);
    response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
    System.out.println(response);
}

public static void createAutomationAccount(String keyStorePath, String keyStorePassword, String subscriptionId)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    String response = "";
    // Create automation
    String automationName = "javaauto";
    String location = "East US 2";

    url = String.format("https://management.core.windows.net/%s/cloudServices/OaaSCSI6EGAZU6F6QTCK5XRVT45FKJC6RC7IQIQW3OPR7SVLE4ZPD4IQQQ-East-US/resources/automation/AutomationAccount/%s?resourceType=AutomationAccount&detailLevel=Full&resourceProviderNamespace=automation", subscriptionId, automationName);

    String requestBody = "<Response xmlns=\"http://schemas.microsoft.com/windowsazure\"><CloudServiceSettings><GeoRegion>East US 2</GeoRegion></CloudServiceSettings><SchemaVersion>1.0</SchemaVersion><Plan>Basic</Plan></Resource>";

    int createResponseCode = processPostRequest(new URL(url), requestBody.getBytes(), "application/xml", keyStorePath, keyStorePassword);

    System.out.println("CreateAutomationAccount " + createResponseCode);
}

// Create a published runbook
public static void createRunbook(String keyStorePath, String keyStorePassword, String subscriptionId)
throws  UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException
{
    String url = "";
    String response = "";
    // Create runbook 
    String runbookName = "Write-HellowWorld";
    String cloudService = <CLOUD_SERVICE>;

    url = String.format("https://management.core.windows.net/%s/cloudServices/%s/resources/automation/~/automationAccounts/javaauto/runbooks/%s?api-version=2014-12-08", subscriptionId, cloudService, runbookName);
    String requestBody = "{ \"tags\":{ \"Testing\":\"show value\", \"Source\":\"TechNet Script Center\" }, \"properties\":{ \"description\":\"Hello world\", \"runbookType\":\"Script\", \"logProgress\":false, \"publishContentLink\":{ \"uri\":\"https://gallery.technet.microsoft.com/scriptcenter/The-Hello-World-of-Windows-81b69574/file/111354/1/Write-HelloWorld.ps1\", \"contentVersion\":\"1.0.0.0\", \"contentHash\":{ \"algorithm\":\"sha256\", \"value\":\"EqdfsYoVzERQZ3l69N55y1RcYDwkib2+2X+aGUSdr4Q=\" } } } }";

    int createResponseCode = processPutRequest(new URL(url), requestBody.getBytes(), "application/json", keyStorePath, keyStorePassword);
    System.out.println("created runbook:: " + createResponseCode);
}

public static void main(String[] args)
{
    try {
        String subscriptionId = "<Insert your subscription ID>"; 
        String keyStorePath = "KeyStore.jks";
        String keyStorePassword = "secret321";

        String cloudService = "1testjava";

        //listImages(keyStorePath, keyStorePassword, subscriptionId);
        listAutomationAccounts(keyStorePath, keyStorePassword, subscriptionId);
        checkCloudServiceAvailability(keyStorePath, keyStorePassword, subscriptionId, cloudService);
        deleteCloudService(keyStorePath, keyStorePassword, subscriptionId, cloudService);
        createCloudService(keyStorePath, keyStorePassword, subscriptionId, cloudService);
        createAutomationAccount(keyStorePath, keyStorePassword, subscriptionId);

        // This also throws an error
        createRunbook(keyStorePath, keyStorePassword, subscriptionId);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

For running this I've created a keystore file Keystore.jks and its .cer file using:

keytool -genkeypair -alias keyfile -keyalg RSA -keystore KeyStore.jks -keysize 2048 -storepass "secret321"

keytool -v -export -file SMAPI.cer -keystore KeyStore.jks -alias keyfile `

The SMAPI.cer was uploaded to the Window Azure Portal, Settings > Management Certificates


Answer:

I checked your code and found out two faults as follows.

  1. Refer to the link https://msdn.microsoft.com/en-us/library/azure/mt163820.aspx, the REST API for create an automation account is by using Http PUT method, not POST method. So I copied your function "processPostRequest" to new function "processPutRequest", and replaced "con.setRequestMethod("POST");" with "con.setRequestMethod("PUT");" and fixed it in the function "createAutomationAccount".

  2. In your function "createAutomationAccount", the root mark name of request body xml is "Resource", not "Response".

It will work correctly until fix the faults.

Best Regards!