Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

Is there a way to hide rows in a table? #119

Closed
jeremymv2 opened this issue Apr 29, 2014 · 8 comments
Closed

Is there a way to hide rows in a table? #119

jeremymv2 opened this issue Apr 29, 2014 · 8 comments

Comments

@jeremymv2
Copy link

I've figured out how to use environment variables passed into the JVM to populate my password variable in a fitnesse table, but the actual password value still gets stored in the output results of the test. Is there a way to hide the table row so that the password variable value never gets displayed?

@raboof
Copy link
Contributor

raboof commented Apr 30, 2014

First off: I think it's kind of suspicious that your test system needs
access to (apparently) sensitive information.

The only way I can think of is by keeping the variable outside of your
FitNesse test entirely, and get it directly from the system properties
inside a fixture. You'd want to have access to some Xebium internals for
that I guess though, filed issue #120 for that.

Kind regards,

Arnout

On Wed, Apr 30, 2014 at 12:16 AM, jeremymv2 [email protected]:

I've figured out how to use environment variables passed into the JVM to
populate my password variable in a fitnesse table, but the actual password
value still gets stored in the output results of the test. Is there a way
to hide the table row so that the password variable value never gets
displayed?


Reply to this email directly or view it on GitHubhttps://github.com//issues/119
.

@wilcokoorn
Copy link

Hi,

Perhaps another option is to abstract the password away from the table and let a Fixture handle it.

Some like this:

Instead of:
| connect | | | |

just use:
| script | MyConnectionFixture |
| connect |

Now the fixture is in control and you can let the fixture retrieve the password in some safe way without any logging.

Just my 2c ;-)

Regards, Wilco.

On 30 Apr 2014, at 14:37, Arnout Engelen <[email protected]mailto:[email protected]> wrote:

First off: I think it's kind of suspicious that your test system needs
access to (apparently) sensitive information.

The only way I can think of is by keeping the variable outside of your
FitNesse test entirely, and get it directly from the system properties
inside a fixture. You'd want to have access to some Xebium internals for
that I guess though, filed issue #120 for that.

Kind regards,

Arnout

On Wed, Apr 30, 2014 at 12:16 AM, jeremymv2 <[email protected]mailto:[email protected]>wrote:

I've figured out how to use environment variables passed into the JVM to
populate my password variable in a fitnesse table, but the actual password
value still gets stored in the output results of the test. Is there a way
to hide the table row so that the password variable value never gets
displayed?


Reply to this email directly or view it on GitHubhttps://github.com//issues/119
.


Reply to this email directly or view it on GitHubhttps://github.com//issues/119#issuecomment-41791196.

@jguglielmi
Copy link

I ran into this issue a little bit ago. While dealing with exposed passwords especially, we preferred Encryption over direct exposure. To encrypt, we prefixed a String with a "decrypt:" tag, passed it into our fixture, and then handled it internally. Below is the OASIS implementation of our augmented SeleniumDriverFixture:

private String encryptString(String password) {

        if (password != null) {
            Cipher aes = null;
            try {
                aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
                aes.init(Cipher.ENCRYPT_MODE, generateKey());
                byte[] ciphertext = aes.doFinal(password.getBytes());
                password = "decrypt:" + bytesToHex(ciphertext);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return password;
    }

    public String bytesToHex(byte[] bytes) {
        final char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[bytes.length * 2];
        int v;
        for ( int j = 0; j < bytes.length; j++ ) {
            v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    public SecretKeySpec generateKey() {
        String passStr="XebiumIsConnectedToTheSikuliBone";
        SecretKey tmp = null;
        try{
            String saltStr = "fijsd@#saltr9jsfizxnv";
            byte[] salt = saltStr.getBytes();
            int iterations = 43210;
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            tmp = factory.generateSecret(new PBEKeySpec(passStr.toCharArray(), salt, iterations, 128));
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return new SecretKeySpec(tmp.getEncoded(), "AES");
    }
}

@jguglielmi
Copy link

And to decrypt the String...

public static String processDecryptionString(String val) {
    if (val.startsWith("decrypt:") ) {
        try {
            val = val.substring(val.indexOf(":") + 1);
            SecretKeySpec key = SikuliResponder.generateKey();
            Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
            aes.init(Cipher.DECRYPT_MODE, key);
            String cleartext = new String(aes.doFinal(hexToBytes(val)));
            return cleartext;
        }
        catch (Exception e) {
            //LOG.info("Exception processDecryptionString:" + e.getMessage());
            e.printStackTrace();
            return val;
        }
    }
    else
        return val;
}

@jeremymv2
Copy link
Author

Thanks folks, you've given me some food for thought. Initially I thought I discovered the solution by using wiki markup to "hide" the part of the fitnesse table:

!***< Hide
| script |
| ensure | do | type | on | id=Password | with | ${pass} |
***
!

My thought was to pass the value of ${pass} in as a JVM argument via Environment variable to the stand-alone fitness client from our CI engine. Even though the value of ${pass} isn't exposed in the test page nor in the "output" of the test page, it still gets stored in plain text in the xml result of the test run.. Abstracting it away from the table and into the fixture code seems to be the way to do it, which will work for our developers who can write fixtures but probably not for most of our QA's who can't code and will realistically only be able to use the simple Xebium dsl "ensure do ...".

@jguglielmi
Copy link

I don't see why not. You can add custom commands to the SeleniumDriverFixture.java file for your testers. They can still use it. We use the old fashioned type command, but just added some conditions prior to passing it into the command processor. You can see for yourself:

private String executeCommand(final ExtendedSeleniumCommand command, final String[] values, long delay) {
    if (LOG.isDebugEnabled()) {
        LOG.debug("executeCommand. Command: " + command.getSeleniumCommand() + " with values: [" + join(values, ", ") +"]");
    }

    if (commandProcessor == null) {
        throw new IllegalStateException("Command processor not running. " +
                        "First start it by invoking startBrowserOnUrl.");
    }


    // Handle special cases first
    if ("pause".equals(command.getSeleniumCommand())) {
        try {
            Thread.sleep(Long.parseLong(values[0]));
        } catch (Exception e) {
            LOG.warn("Pause command interrupted", e);
        }
        return null;
    }

    if ("contextMenu".equals(command.getSeleniumCommand())) {
        try {
            WebElement webElement = getWebDriver().findElement(By.xpath(values[0]));
            new Actions(getWebDriver()).contextClick(webElement).perform();
            LOG.info("Performing | contextMenu | " + values[0] + " | " );
        } catch (Exception e) {
            LOG.warn("contextMenu command interrupted", e);
        }
        return null;
    }

    String output = null;
    try {
        if (command.returnTypeIsArray()) {
            output = executeArrayCommand(command.getSeleniumCommand(), values);
        } else {
            output = executeCommand(command.getSeleniumCommand(), values);
        }
    } catch (final SeleniumException e) {
        output = "Execution of command failed: " + e.getMessage();
        LOG.error(output);
        if (!(command.isAssertCommand() || command.isVerifyCommand() || command.isWaitForCommand())) {
            throw e;
        }
    }

    if (command.isAndWaitCommand()) {
        commandProcessor.doCommand("waitForPageToLoad", new String[] { "" + timeout });
    }

    if (delay > 0) {
        try {
            Thread.sleep(delay);
        } catch (Exception e) {
            LOG.warn("Step delay sleep command interrupted", e);
        }
    }
    return output;
}

@jguglielmi
Copy link

You'd just add "type" to the list and specify the methods to decrypt first just like the "contextMenu" example. It'll then get passed to the commandProcessor as plain text.

@jeremymv2
Copy link
Author

Thanks, this is what I needed :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants