/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License;
 * you may not use this file except in compliance with the Elastic License.
 */
package org.elasticsearch.shield.signature.tool;

import org.elasticsearch.common.cli.CliTool;
import org.elasticsearch.common.cli.CliToolConfig;
import org.elasticsearch.common.cli.Terminal;
import org.elasticsearch.common.cli.commons.CommandLine;
import org.elasticsearch.common.collect.Sets;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.signature.InternalSignatureService;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Set;

import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd;
import static org.elasticsearch.common.cli.CliToolConfig.config;

/**
 *
 */
public class SystemKeyTool extends CliTool {

    public static final Set<PosixFilePermission> PERMISSION_OWNER_READ_WRITE = Sets.newHashSet(PosixFilePermission.OWNER_READ,
        PosixFilePermission.OWNER_WRITE);


    public static void main(String[] args) throws Exception {
        int status = new SystemKeyTool().execute(args);
        System.exit(status);
    }

    private static final CliToolConfig CONFIG = config("syskey", SystemKeyTool.class)
            .cmds(Generate.CMD)
            .build();

    public SystemKeyTool() {
        super(CONFIG);
    }

    @Override
    protected Command parse(String cmd, CommandLine commandLine) throws Exception {
        return Generate.parse(terminal, commandLine);
    }

    static class Generate extends Command {

        private static final CliToolConfig.Cmd CMD = cmd("generate", Generate.class).build();

        final Path path;

        Generate(Terminal terminal, Path path) {
            super(terminal);
            this.path = path;
        }

        public static Command parse(Terminal terminal, CommandLine cl) {
            String[] args = cl.getArgs();
            if (args.length > 1) {
                return exitCmd(ExitStatus.USAGE, terminal, "Too many arguments");
            }
            Path path = args.length != 0 ? Paths.get(args[0]) : null;
            return new Generate(terminal, path);
        }

        @Override
        public ExitStatus execute(Settings settings, Environment env) throws Exception {
            Path path = this.path;
            if (path == null) {
                path = InternalSignatureService.resolveFile(settings, env);
            }
            terminal.println(Terminal.Verbosity.VERBOSE, "generating...");
            byte[] key = InternalSignatureService.generateKey();
            terminal.println("Storing generated key in [%s]", path.toAbsolutePath());
            Files.write(path, key, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);

            boolean supportsPosixPermissions = Files.getFileStore(path).supportsFileAttributeView(PosixFileAttributeView.class);
            if (supportsPosixPermissions) {
                Files.setPosixFilePermissions(path, PERMISSION_OWNER_READ_WRITE);
                terminal.println("Ensure the generated key can be read by the user that Elasticsearch runs as, permissions are set to owner read/write only");
            }

            return ExitStatus.OK;
        }
    }

}

@@ -692,16 +692,44 @@
 rvice;%0A%0A
+import java.io.IOException;%0A
 import j
@@ -2650,24 +2650,46 @@
  this.path;%0A
+            try %7B%0A    
             
@@ -2704,24 +2704,28 @@
  == null) %7B%0A
+    
             
@@ -2792,34 +2792,42 @@
 v);%0A            
-%7D%0A
+    %7D%0A    
             term
@@ -2897,16 +2897,20 @@
         
+    
 byte%5B%5D k
@@ -2958,32 +2958,36 @@
 ();%0A            
+    
 terminal.println
@@ -3017,16 +3017,19 @@
  in %5B%25s%5D
+...
 %22, path.
@@ -3047,16 +3047,20 @@
 ath());%0A
+    
         
@@ -3151,16 +3151,223 @@
 ISTING);
+%0A            %7D catch (IOException ioe) %7B%0A                terminal.printError(%22Cannot generate and save system key file %5B%25s%5D%22, path.toAbsolutePath());%0A                return ExitStatus.IO_ERROR;%0A            %7D
 %0A%0A      
@@ -3529,24 +3529,50 @@
 missions) %7B%0A
+                try %7B%0A    
             
@@ -3641,16 +3641,267 @@
 WRITE);%0A
+                %7D catch (IOException ioe) %7B%0A                    terminal.printError(%22Cannot set owner read/write permissions to generated system key file %5B%25s%5D%22, path.toAbsolutePath());%0A                    return ExitStatus.IO_ERROR;%0A                %7D%0A
         

Provide better error messages for syskey cli tool