#!/usr/bin/ruby

module OpenSecret

# This Jenkins use case handles the to and fro integration of secrets and sensitive information
# between the safe database under management and a Jenkins service pinpointed by an incoming 
# host url parameter.
#
# This Jenkins use case injects for example the AWS IAM user access key, secret key and region key
# into a running Jenkins CI (Continuous Integration) service at the specified (url) location.
#
#     safe jenkins post <<[ aws | docker | git ]>> <<jenkins-host-url>>

class Jenkins < UseCase

    attr_writer :command, :service, :url

    JENKINS_URL_POSTFIX = "credentials/store/system/domain/_/createCredentials"
    JENKINS_URL_PATH = "/credentials/store/system/domain/_/createCredentials"
    REQUEST_CONTENT_TYPE = 'application/json;charset=UTF-8'

    DATA_DICTIONARY = {
                "scope"       => "GLOBAL",
                "id"          => "safe.aws.region.key",
                "secret"      => "blahblahblah",
                "description" => "The AWS region key for example eu-west-1 for Dublin in Ireland.",
                "$class"      => "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
            }

### DICTIONARY_TO_POST = { “” => “0”, “credentials” => DATA_DICTIONARY }

DICTIONARY_TO_POST = { "credentials" => DATA_DICTIONARY }

def json_api_post_request_2

    require 'net/http'
    require 'json'

    http = Net::HTTP.new( "localhost", "8080" )

########### service_url = File.join( @url, JENKINS_URL_POSTFIX )

request = Net::HTTP::Post.new( JENKINS_URL_PATH )
uri_encoded_json = URI::encode( DICTIONARY_TO_POST.to_json )
request.body = uri_encoded_json
request.content_type = REQUEST_CONTENT_TYPE

response = http.request( request )

### uri = URI.parse( “#{service_url}” ) ### req = Net::HTTP::Post.new(uri) ### req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')

### res = Net::HTTP.start(uri.hostname, uri.port) do |http| ### http.request(req) ### end

    puts response.body

end

def json_api_post_request_1

    require 'net/http'
    require 'json'

    begin
        service_url = File.join( @url, JENKINS_URL_POSTFIX )

        puts ""
        puts "The service_url is #{service_url}"

        uri = URI( service_url )

        puts "The simple URI hostname is #{uri.host}"
        puts "Data will be sent via the URI port numbered [#{uri.port}]"
        puts "The URI path string is #{uri.path}"

        http = Net::HTTP.new(uri.host, uri.port)

#### req = Net::HTTP::Post.new(uri.path, {'Content-Type' =>'application/json',

#### 'Authorization' => 'XXXXXXXXXXXXXXXX'})

### our_request = Net::HTTP::Post.new( uri.path, { 'Content-Type' =>'application/json' } ) ############## our_request.body = {“pizza_type” => “Margherita”, “pizza_no” => “2”}.to_json

jenkins_inner_dictionary = {
    "scope"       => "GLOBAL",
    "id"          => "safe.aws.region.key",
    "secret"      => "blahblahblah",
    "description" => "The AWS region key for example eu-west-1 for Dublin in Ireland.",
    "$class"      => "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
}

jenkins_outer_dictionary = { "" => "0", "credentials" => jenkins_inner_dictionary }

our_request = Net::HTTP::Post.new( uri.path )
our_request.set_form_data( jenkins_outer_dictionary.to_json )

##### our_request.set_form_data( jenkins_inner_dictionary )

#### jenkins_jason_dictionary = jenkins_outer_dictionary.to_json #### our_request.body = jenkins_jason_dictionary

## http = Net::HTTP.new(“api.restsite.com”)

## request = Net::HTTP::Post.new(“/users”) ## request.set_form_data({“users” => “quentin”}) ## response = http.request(request)

## DELETE ME ## DELETE ME ## DELETE ME

puts "The [[[ SENSITIVE ]] JSON request body is this.\n\n #{our_request.body}"
puts ""

res = http.request( our_request )

puts res.body

##### puts JSON.parse(res.body)

        rescue => e

            puts "failed #{e}"

        end

    end

def execute

  return unless ops_key_exists?
  master_db = get_master_database()
  return if unopened_envelope?( master_db )

  # Get the open chapter identifier (id).
  # Decide whether chapter already exists.
  # Then get (or instantiate) the chapter's hash data structure
  chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
  verse_id = master_db[ KEY_PATH ]
  chapter_exists = OpenKey::KeyApi.db_envelope_exists?( master_db[ chapter_id ] )

  # Unlock the chapter data structure by supplying
  # key/value mini-dictionary breadcrumbs sitting
  # within the master database at the section labelled
  # envelope@<<actual_chapter_id>>.
  chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) )

  # Now read the three AWS IAM credentials @access.key, @secret.key and region.key
  # into the 3 environment variables terraform expects to find.

  # ----------------------------------------------------------------------------------------------------- #
  # ----------------------------------------------------------------------------------------------------- #

  # -- 
  # --  Reading material for CUrl like activities using net/http core ruby library
  # -- 
  # --     ssl/https/rest  =>  http://www.rubyinside.com/nethttp-cheat-sheet-2940.html
  # --     official docs   =>  https://ruby-doc.org/stdlib-2.4.1/libdoc/net/http/rdoc/Net/HTTP.html
  # --                     =>  
  # --                     =>  
  # --                     =>  
  # --                     =>  
  # -- 

  # ----------------------------------------------------------------------------------------------------- #
  # ----------------------------------------------------------------------------------------------------- #

  json_api_post_request_2

  puts ""
  puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  puts ""

begin

ENV[ "AWS_ACCESS_KEY_ID"     ] = chapter_data[ verse_id ][ "@access.key" ]
ENV[ "AWS_SECRET_ACCESS_KEY" ] = chapter_data[ verse_id ][ "@secret.key" ]
ENV[ "AWS_DEFAULT_REGION"    ] = chapter_data[ verse_id ][ "region.key"  ]

auto_approve = @command && @command.eql?( "plan" ) ? "" : "-auto-approve"
command_name = @command ? @command : "apply"

puts ""
puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
puts ""

system "terraform #{command_name} #{auto_approve}"

puts ""
puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
puts ""

end

    # ############## | ############################################################
    # @todo refactor | ############################################################
    # -------------- | 000000000000000000000000000000000000000000000000000000000000
    # export-then-execute
    # -------------------
    # Refactor all this code into a generic export-then-execute use case
    # Then you pass in a Key/Value Dictionary
    #
    # { "AWS_ACCESS_KEY_ID" => "@access_key",
    #   "AWS_SECRET_ACCESS_KEY" => "@secret_key",
    #   "AWS_DEFAULT_REGION" => "region_key"
    # }
    #
    # And pass in a command array [ "terraform #{command_name} #{auto_approve}", "terraform graph ..." ]
    #
    # Validation is done by the generic use case (which loops checking that every value exists
    # as a key at the opened location.
    #
    # If all good the generic use case exports the ENV vars and runs each command in the list.
    # PS - configure map in INI not code file
    #
    # The extra power will speed up generation of environment variable use cases including
    # ansible, s3 bucket operations, git interactions and more.
    #
    # ############## | ############################################################
    # ############## | ############################################################

  end

end

end